Why do I get a NullPointerExeption for testManuscript when trying to run my test?
This is my Manuscript.java:
package org.lhoffjann;
public class Manuscript {
private String msID;
private String path;
public void setMSid(String msID){
this.msID = msID;
}
public String getMSid() {
return this.msID;
}
}
This is my ManuscriptTest.java:
package org.lhoffjann;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ManuscriptTest {
private static Manuscript testManuscript;
#Before
public void setUp(){
testManuscript = new Manuscript();
}
#Test
public void testGetMSid() {
testManuscript.setMSid("1234");
assertTrue("1234" == testManuscript.getMSid());
}
}
You have imported #Test from JUnit 5, while you're using #Before from JUnit 4, that combination doesn't work. You need to choose which JUnit version you want to use, 4 or 5, and then consistently import classes from that JUnit version. I would recommend using JUnit 5, and removing all JUnit 4 dependencies from your classpath, or at least configure your IDE to not suggest those imports.
For this specific case, replace #Before (org.junit.Before) with #BeforeEach (org.junit.jupiter.api.BeforeEach).
In the example as shown, you don't even need this setUp method, as each test-execution gets its own instance of the test class. You can use:
private Manuscript testManuscript = new Manuscript();
That is, remove static, initialize the field directly, and remove the setUp method.
Even if you continue to use the setUp method, I recommend removing the static, so testManuscript is an instance field, like it is actually used.
You have mixed Junit4 with Junit5. You should use only one version.
Junit4 or
package org.lhoffjann;
import org.junit.Before;
import org.junit.Test;
import org.junit.Assert;
public class ManuscriptTest {
private static Manuscript testManuscript;
#Before
public void setUp(){
testManuscript = new Manuscript();
}
#Test
public void testGetMSid() {
testManuscript.setMSid("1234");
Assert.assertEquals("1234",testManuscript.getMSid());
}
or
Junit5
package org.lhoffjann;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ManuscriptTest {
private static Manuscript testManuscript;
#BeforeEach
public void setUp() {
testManuscript = new Manuscript();
}
#Test
void testGetMSid() {
testManuscript.setMSid("1234");
Assertions.assertEquals("1234", testManuscript.getMSid());
}
}
Related
I want to mock the static method being invoked from the constructor of my class.
My class:
package com.javaeasily.demos.junit;
import java.util.ArrayList;
public class MyClass {
private int number;
private static final ArrayList<String> ACTIVE_SERVICES_POST_RECONFIGURE = new ArrayList<>();
// Only allow construction if number is greater than one
MyClass() {
ACTIVE_SERVICES_POST_RECONFIGURE.add("my-node-" + NodeUtils.getMyNode());
}
public void reconfigureNode() {
if (ACTIVE_SERVICES_POST_RECONFIGURE.isEmpty()) {
return;
}
}
}
Here NodeUtils.getMyNode() is the static method being invoked from the constructor of the class.
NodeUtils.java Class:
package com.javaeasily.demos.junit;
import org.apache.maven.surefire.shade.booter.org.apache.commons.lang3.StringUtils;
public class NodeUtils {
private static final String HOSTNAME_PREFIX = "my-node-";
public static String hostnameToNode(String hostname) {
if (!hostname.startsWith(HOSTNAME_PREFIX)) {
throw new IllegalArgumentException(hostname + " is not recognized hostname");
}
return StringUtils.removeStart(hostname, HOSTNAME_PREFIX);
}
public static String getHostname() {
return System.getenv("HOSTNAME");
}
public static String getMyNode() {
return hostnameToNode(getHostname());
}
}
MyClassTest.java
package com.javaeasily.demos.junit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class MyClassTest {
private MyClass myclass;
#BeforeEach
public void SetUp() {
myclass = new MyClass();
}
#Test
public void testReconfigureNode() {
myclass.reconfigureNode();
}
}
When I try & run the only test case I get the following error:
java.lang.NullPointerException
at com.javaeasily.demos.junit.NodeUtils.hostnameToNode(NodeUtils.java:8)
at com.javaeasily.demos.junit.NodeUtils.getMyNode(NodeUtils.java:19)
at com.javaeasily.demos.junit.MyClass.<init>(MyClass.java:12)
at com.javaeasily.demos.junit.MyClassTest.SetUp(MyClassTest.java:11)
I am not sure how do we mock the method to avoid this error?
Since I am new to Java I am not able to catch this. Any help here is appreciated.
So to answer your question how to mock a static method: mockito allows this since version 3.8.0. You can find a tutorial here at Baeldung
This allows generating a statically mocked Object for a concrete context, which you can create within a try block. For your case this would look like the following.
Fixed Unit Test
package com.javaeasily.demos.junit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
public class MyClassTest {
private MyClass myclass;
#BeforeEach
public void SetUp() {
try (MockedStatic<NodeUtils> nodeUtilsMockedStatic = Mockito.mockStatic(NodeUtils.class)) {
nodeUtilsMockedStatic.when(NodeUtils::getMyNode).thenReturn("foo");
myclass = new MyClass();
}
}
#Test
public void testReconfigureNode() {
myclass.reconfigureNode();
}
}
Mockito dependency
You need mockito with at least version 3.8.0 in your project.
With maven add:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
With gradle add:
testImplementation group: 'org.mockito', name: 'mockito-inline', version: '3.8.0'
I'm currently working at a Java application that I'm testing using JUnit Jupiter. I am starting to work at the GUI and I was wondering if it was possible to use AssertJ-Swing with JUnit 5.
As a matter of fact I have found an open issue on AssertJ-Swing GitHub page.
The suggestion they give is to define a GUITestExtension like so:
import org.assertj.swing.junit.runner.ImageFolderCreator;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import java.lang.reflect.Method;
import static org.assertj.swing.annotation.GUITestFinder.isGUITest;
import static org.assertj.swing.junit.runner.Formatter.testNameFrom;
/**
* Understands a JUnit 5 extension that takes a screenshot of a failed GUI test.
* The Junit 4 runner is available in {#link org.assertj.swing.junit.runner.GUITestRunner}.
*
* #see assertj-swing #259
* #author William Bakker
*/
public class GUITestExtension implements Extension, InvocationInterceptor {
private final FailureScreenshotTaker screenshotTaker;
public GUITestExtension() {
screenshotTaker = new FailureScreenshotTaker(new ImageFolderCreator().createImageFolder());
}
#Override
public void interceptTestMethod(
Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext)
throws Throwable {
try {
invocation.proceed();
} catch (Throwable t) {
takeScreenshot(invocationContext.getExecutable());
throw t;
}
}
private void takeScreenshot(Method method) {
final Class<?> testClass = method.getDeclaringClass();
if (!(isGUITest(testClass, method)))
return;
screenshotTaker.saveScreenshot(testNameFrom(testClass, method));
}
}
I am a bit familiar with the GUITestRunner that can be used with JUnit 4, but I have no idea on how to replace it with this.
Note:
Usually GUITestRunner is used like so with JUnit 4:
import org.assertj.swing.junit.runner.GUITestRunner;
import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
import org.junit.runner.RunWith;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
#RunWith(GUITestRunner.class)
public class WelcomeSwingViewTest extends AssertJSwingJUnitTestCase{
private FrameFixture window;
private WelcomeSwingView welcomeSwingView;
#Override
protected void onSetUp() {
GuiActionRunner.execute(() -> {
welcomeSwingView = new WelcomeSwingView();
return welcomeSwingView;
});
window = new FrameFixture(robot(), welcomeSwingView);
window.show();
}
}
Any help is appreciated.
Assuming that the GUITestExtension mentioned in the issue is defined in your codebase, it could be registered in the following way:
#Test
#ExtendWith(GUITestExtension.class)
void test() {
...
}
More can be found in the extension model section of the JUnit 5 documentation.
Ideally, the extension should come directly from AssertJ Swing, but the project lead has no longer time for it, unfortunately, therefore we are looking for committers.
If anyone is interested, feel free to get in touch on GitHub.
I changed my test class according to Stefano's answer, and now everything is working. In case anyone needs it my test class code is something like this:
import org.assertj.swing.core.matcher.JLabelMatcher;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.assertj.swing.annotation.GUITest;
#ExtendWith(GUITestExtension.class)
class WelcomeSwingViewTest {
private FrameFixture window;
private WelcomeSwingView welcomeSwingView;
#BeforeAll
static void setUpOnce() {
FailOnThreadViolationRepaintManager.install();
}
#BeforeEach
void setup() {
GuiActionRunner.execute(() -> {
welcomeSwingView = new WelcomeSwingView();
return welcomeSwingView;
});
window = new FrameFixture(welcomeSwingView);
window.show();
}
#AfterEach
void clean() {
window.cleanUp();
}
#Test #GUITest
void testControlsInitialStates() {
window.label(JLabelMatcher.withText("label"));
}
}
Of course you also have to import the GUITestExtension (defined as in my question) to your test class. Also the test is successful because in my view I have a label with text "label".
I am getting
java.lang.NoSuchMethodError: org.junit.jupiter.api.extension.ExtensionContext.getRequiredTestInstances()Lorg/junit/jupiter/api/extension/TestInstances;
at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:143)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$null$0(TestMethodTestDescriptor.java:126)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
error for below code.
what the proper way of running below code as junit test?
package com.safnas.unittesting.unittesting.business;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.safnas.unittesting.unittesting.data.SomeDataService;
#ExtendWith(MockitoExtension.class)
class SomeBusinessMockTest {
#InjectMocks
SomeBusinessImpl business = new SomeBusinessImpl();
#Mock
SomeDataService dataServiceMock;
#Test
void calculateSumUsingDataService_basic() {
when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {1,2,3});
assertEquals(6, business.calculateSumUsingDataService());
}
#Test
void calculateSum_empty() {
when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {});
assertEquals(0, business.calculateSumUsingDataService());
}
#Test
void calculateSum_oneValue() {
when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {5});
assertEquals(5, business.calculateSumUsingDataService());
}
}
I removed #ExtendWith(MockitoExtension.class) and used below
#BeforeEach
void beforeEach() {
MockitoAnnotations.openMocks(this);
}
it worked fine
as per javadocs
AutoCloseable org.mockito.MockitoAnnotations.openMocks(Object testClass)
Initializes objects annotated with Mockito annotations for given testClass:#org.mockito.Mock, #Spy, #Captor, #InjectMocks
See examples in javadoc for MockitoAnnotations class.
Parameters:testClass Returns:A closable to close when completing any tests in testClass.
one more observation.
without any change, my original question is working in intelliJ
eclipse is only having issue it seems
I have a short piece of code and two unit test. Strangely when I launch the test separately they works well but when I launch them together it look like the second method use the "when" of the first method.
Tested method :
public ProductIssuer update(ProductIssuer productIssuer) {
findById(productIssuer.getId())
.orElseThrow(() -> new B4FinanceException(ErrorCode.USER_NOT_FOUND, "Please provide an existing user"));
return productIssuerRepository.save(productIssuer);
}
The tests :
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class ProductIssuerServiceTest {
#InjectMocks
private static ProductIssuerService productIssuerService;
#Mock
private static ProductIssuerRepository productIssuerRepository;
public static final UUID DEFAULT_UUID = UUID.fromString("b8fc499a-2084-11e8-b467-0ed5f89f0000");
private static final String DEFAULT_NAME = "productIssuer Name";
#BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateNotFoundThrowException() {
ProductIssuer productIssuer = new ProductIssuer();
productIssuer.setName(DEFAULT_NAME);
when(productIssuerRepository.findById(any())).thenReturn(Optional.empty());
assertThatExceptionOfType(B4FinanceException.class).isThrownBy(() -> productIssuerService.update(productIssuer));
}
#Test
public void update() {
ProductIssuer productIssuer = new ProductIssuer();
productIssuer.setName(DEFAULT_NAME);
productIssuer.setId(DEFAULT_UUID);
when(productIssuerRepository.findById(any())).thenReturn(Optional.of(productIssuer));
when(productIssuerRepository.save(any())).thenReturn(productIssuer);
productIssuerService.update(productIssuer);
}
}
The result is ok for the first test (updateNotFoundThrowException) but for the second test I got a "Please provide an existing user" error.
I want to test the following example code:
public class Example {
...
public void doStuff() {
...
Lift lift = new Lift();
lift.call(5);
...
}
...
}
How can I 'intercept' lift.call(5)?
Generally I would use when(lift.call(anyInt()).thenReturn(...), but I have no reference to the Lift object.
You can't do it with mockito alone. The cleanest solution is to refactor your code so you can have access to it. However if that's not an option then "power mockito" is what you want. Grab "powermock-api-mockito"+"powermock-module-junit4" and then something like this will do the trick:
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Example.class)
public class ExampleTest {
private Example testSubject;
#Mock
private Lift lift;
#Test
public void testDoStuff() throws Exception {
testSubject.doStuff();
verify(lift).call(5);
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.whenNew(Lift.class).withNoArguments().thenReturn(lift);
testSubject = new Example();
}
}
Can you modify the Example class? If yes, the simplest way would be to extract the Lift dependency and provide it via constructor. Like this:
public class Example {
private final Lift lift;
public Example(Lift lift) {
this.lift = lift;
}
public void doStuff() {
this.lift.call(5);
}
}
Then you can stub lift as you want since now you have access to the instance.