问题
I took a working test written for JUnit using Mockito and tried to adapt it to work with TestNG but oddly using TestNG only one test will work.
I think it is somehow related to the resetting of the mocks but I have played around with trying to call Mockito.reset and using BeforeMethod and BeforeClass and different combinations but still can only get one test to pass.
What I need to do to get the test to work?
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(calculatorController).build();
}
@AfterMethod
public void reset() {
Mockito.reset(calculatorService);
}
@Test
public void addFunctionTest() throws Exception {
Assert.assertNotNull(calculatorController);
Result expectedResult = new Result();
expectedResult.setResult(10);
when(calculatorService.add(anyInt(), anyInt())).thenReturn(expectedResult);
mockMvc.perform(get("/calculator/add").accept(MediaType.APPLICATION_JSON_VALUE)
.param("val1", "100")
.param("val2", "100"))
.andExpect(content().contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.result", equalTo(10)));
verify(calculatorService, times(1)).add(anyInt(), anyInt());
}
@Test
public void subtractFunctionTest() throws Exception {
Assert.assertNotNull(calculatorController);
Result expectedResult = new Result();
expectedResult.setResult(90);
when(calculatorService.subtract(anyInt(), anyInt())).thenReturn(expectedResult);
mockMvc.perform(get("/calculator/subtract").accept(MediaType.APPLICATION_JSON_VALUE)
.param("val1", "100")
.param("val2", "10"))
.andExpect(content().contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.result", equalTo(90)));
verify(calculatorService, times(1)).subtract(anyInt(), anyInt());
}
The second test always seems to fail on assertions that either content type is not set or the expected result is wrong.
It seems like the response for the first test is somehow being evaluated in the second test and so is obviously wrong!
I know the controller and service work as expected and the exact same tests running with jUnit actually work ok.
I have managed to get the tests to perform properly only when I do the following:
@BeforeGroups("subtract")
public void reset() {
Mockito.reset(calculatorService);
mockMvc = MockMvcBuilders.standaloneSetup(calculatorController).build();
}
@Test(groups = "subtract")
public void subtractFunctionTest() throws Exception {
System.out.println("***** IN METHOD *****");
Assert.assertNotNull(calculatorController);
Result expectedResult = new Result();
expectedResult.setResult(90);
when(calculatorService.subtract(anyInt(), anyInt())).thenReturn(expectedResult);
//Perform HTTP Get for the homepage
mockMvc.perform(get("/calculator/subtract").accept(MediaType.APPLICATION_JSON_VALUE)
.param("val1", "100")
.param("val2", "10"))
.andExpect(content().contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.result", equalTo(90)));
//Verify that the service method was only called one time
verify(calculatorService, times(1)).subtract(anyInt(), anyInt());
}
This means I need to add one of these reset methods for each test method though and I then need a group per test method which doesnt seem correct.
回答1:
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.
来源:https://stackoverflow.com/questions/37591644/using-mockito-with-testng