Using Mockito with TestNG
There is a difference in the behaviour of these frameworks:
- JUnit creates a new instance of class for every of its test methods. This means that the fields are not shared between tests.
- But TestNG creates only one object and thus the state in fields is shared between to
@Test
s
For Mockito you need to init mocks before every test method so that the state is not shared between two @Test
s in TestNG:
@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
}
For JUnit it works out of box because 2nd @Test
has its own fields and its own mocks.
I'm not sure, if this answer fits to the questioners problem, because the mocks are not listed. But I'd like to re-state one comment from andy in the accepted answer, which helped me out on the same problem. Here are some more details and an example:
public class B {
private A a;
B (A a) {
this.a = a
}
// ...
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class MyTest {
@Mock
A a;
@InjectMocks
B B;
@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
void test1() {
// ...
// b.toString();
// b.getA().toString();
// a.toString();
}
@Test
void test2() {
// ...
// b.toString();
// b.getA().toString();
// a.toString();
}
@AfterMethod
public void reset()
{
// Solution:
b = null;
}
}
Mockitos MockitoAnnotations.initMocks(this)
only re-initializes mocks, as Mockito.reset(a)
only resets mocks. The problem is the class under test, which is annotated with @InjectMocks
. This class, here named B
, is not initialized again. It is initialized for the first test with a mock of A
, the mock of A
is re-initialized but B
still contains the first version of A
.
The solution is to reset the class under test manually with b = null
at any plausible place (@AfterMethod
or before initMocks
). Then Mockito also re-inizialized the class under test B
.
You can also use MockitoTestNGListener it is similar to JUnit
MockitoJUnitRunner
or MockitoExtension
.
Example of code:
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import java.util.Map;
@Listeners(MockitoTestNGListener.class)
public class MyTest {
@Mock
Map map;
@InjectMocks
SomeType someType;
@Test
void test() {
// ...
}
}