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
Related
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());
}
}
I am unable to run JUnit5 tests concurrently when they involve using SpringExtension. When I run sequentially, there are no issues. When I run concurrently, only one test in the class is able to successfully access any injected or autowired fields. Any other tests will throw a NullPointerException when attempting to reference injected or autowired fields. Since JUnit5 parallelization is using ForkJoinPool under the hood, I was under the impression one Spring test context would be created and threads could safely use a cached context. Am I missing something in configuring my testing suite?
Here's a simplified example where the problem can be observed:
DummyTest:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.inject.Inject;
#Execution(ExecutionMode.CONCURRENT)
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {DummyTestConfig.class})
public class DummyTest {
#Inject
private StringBuilder stringBuilder;
#Test
public void testA() {
Assertions.assertEquals(stringBuilder.toString(), "test");
}
#Test
public void testB() {
Assertions.assertEquals(stringBuilder.toString(), "test");
}
}
DummyTestConfig:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class DummyTestConfig {
public DummyTestConfig() {}
#Bean
public StringBuilder stringBuilder() {
return new StringBuilder("test");
}
}
#RunWith(SpringRunner.class)
public class TestService {
#Test
#EnabledIf("Instant.now().atZone(ZoneId.of(\"Asia/Kolkata\")).getDayOfWeek() == DayOfWeek.MONDAY")
public void test() {
System.out.println("The day is Monday");
}
}
running using mvn -Dtest=TestService test
#EnabledIf is not working, it is executing the test even the day is not Monday
Your code has two big problems:
First, the test class is annotated with #RunWith(SpringRunner.class) and (because the test runs) the test method is annotated with #org.junit.Test
This means that the test is running using the JUnit4 testing framework and JUnit4 knows nothing about the #EnabledIf annotation and ignores it.
If you want to use the #EnabledIf annotation you must make your test into a JUnit5 test and for that you must change your test class to
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
public class TestService {
#Test
#EnabledIf("Instant.now().atZone(ZoneId.of(\"Asia/Kolkata\")).getDayOfWeek() == DayOfWeek.MONDAY")
public void test() {
System.out.println("The day is Monday");
}
}
Because of the second problem that doesn't completely solve your problem. The documentation for #EnabledIf states:
A container or test may be enabled or disabled based on the boolean return of a method via the #EnabledIf and #DisabledIf annotations. The method is provided to the annotation via its name.
That means that you cannot provide some arbitrary expression as the argument of the #EnabledIf annotation - you need to implement the expression in a method.
When adding that method your test class might look like this:
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
public class TestService {
#Test
#EnabledIf("onMonday")
public void test() {
System.out.println("The day is Monday");
}
static boolean onMonday() {
return Instant.now().atZone(ZoneId.of("Asia/Kolkata")).getDayOfWeek() == DayOfWeek.MONDAY;
}
}
If however you intended to use org.springframework.test.context.junit.jupiter.EnabledIf (instead of org.junit.jupiter.api.condition.EnabledIf - unfortunately your question is not clear about that) then you need to adjust the imports and provide a SpEL-Expression for the condition:
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.EnabledIf;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
public class TestService {
#Test
#EnabledIf("#{T(java.time.Instant).now().atZone(T(java.time.ZoneId).of(\"Asia/Kolkata\")).getDayOfWeek() == T(java.time.DayOfWeek).MONDAY}")
public void test() {
System.out.println("The day is Monday");
}
}
I have a problem using Eclipse to debug Mockito based unittests. Tests are working fine but I cannot step in to spied code or stop on any breakpoint. Debugger is working fine in IntelliJ, but not in Eclipse.
I put a simple unittest to demonstrate my problem. I have JUnit test for SomeService which calls AnotherService. I'm using Mockito to mock output of AnotherService
SomeService.java
package com.example.my;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class SomeService {
#Autowired
private AnotherService anotherService;
public void callBoom() {
System.out.print(anotherService.boom());
}
}
AnotherClass.java
package com.example.my;
import org.springframework.stereotype.Service;
#Service
public class AnotherService {
public String boom() {
return "boom";
}
}
SomeServiceTest.java
package com.example.my;
import static org.mockito.Mockito.doReturn;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
class SomeServiceTest {
#Spy
#InjectMocks
private SomeService someService;
#Mock
private AnotherService anotherService;
#BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doReturn("BOOM!!!").when(anotherService).boom();
}
#Test
void testBoom() {
someService.callBoom();
}
}
I can see "BOOM!!!" printed, so mock is working. But if I put breakpoint into callBoom, Eclipse never stop on it. For other tests it doesn't stop at any method of "spied" beans. When you have larger unittest inability to debug it is very frustrating. I'm running Eclipse 2019-09 with JDK 1.8.0.221, but tried it on 2020-03 as well.
Is it a bug of Powermock or I'm doing sth wrong?
The following test should pass, but failed with:
trackBugPartialMockCountMore(com.xiaomi.finddevice.test.testcase.PowerMockBug)
org.mockito.exceptions.verification.TooManyActualInvocations:
classToMock.foo();
Wanted 1 time:
-> at com.xiaomi.finddevice.test.testcase.PowerMockBug.trackBugPartialMockCountMore(PowerMockBug.java:24)
But was 3 times. Undesired invocation:
-> at com.xiaomi.finddevice.test.testcase.PowerMockBug.trackBugPartialMockCountMore(PowerMockBug.java:22)
When I remove #PrepareForTest(ClassToMock.class), every thing goes well and the test get passed.
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassToMock.class)
public class PowerMockBug {
#Test
public void trackBugPartialMockCountMore() {
ClassToMock mock = mock(ClassToMock.class);
when(mock.foo()).thenCallRealMethod();
mock.foo();
verify(mock).foo();
}
}
class ClassToMock {
public int foo() { return 0x10; }
}
VERSION: powermock-mockito-junit-1.6.3
In your example you don't need to use PowerMock because you are not mocking/spying a final or static method. You can safely remove both #RunWith and #PrepareForTest annotations. Only mockito is needed for your purposes