问题
I have seen example , how to call spring controller using mockito.
Using Mock I call Spring MVC controller. Controller Invokes Spring service class.
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
public class TestController {
@Mock
private TestService testService;
@InjectMocks
private PaymentTransactionController paymentController;
private MockMvc mockMvc;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.setMockMvc(MockMvcBuilders.standaloneSetup(paymentController).build());
}
@Test
public void test() throws Exception {
this.mockMvc.perform(post("/tr/test").content(...)).andExpect(status().isOk());
// testService.save(); <-- another way
}
Ok it works well. I calls my Spring controller very well. But In Spring controller I have Injected Service Layer.
@Autowired
private TestService serviceTest;
@RequestMapping(value = "/test", method = RequestMethod.POST)
@ResponseBody()
public String test(HttpServletRequest request) {
...
serviceTest.save();
// in save method I call dao and dao perist data;
// I have injected dao intrface in serviceTest layer
...
return result;
}
The problem is that, my app does not invokes save method, it is not entered in it. I have no error too. The same result is when I call save() method from Junit (I have commented it in test() method).
When I debug, I have seen that interrupt method happens of org.mockito.internal.creation.MethodInterceptorFilter
How to solve this problem? what happens?
回答1:
If you are doing a unit test of your controller, you should mock the service layer (what you are doing). In this kind of test, you just control that :
- the correct methods of the controller are triggered and they produce what is expected
- the correct methods in service layer are called ... in the mock
You simply have to configure the return values of the methods of the mock (if relevant), or control what was called
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.setMockMvc(MockMvcBuilders.standaloneSetup(paymentController).build());
// set return values from the mocked service
when(testService.find(1)).thenReturn(...);
}
and verify later what has been called
@Test
public void test() throws Exception {
this.mockMvc.perform(post("/tr/test").content(...)).andExpect(status().isOk());
// testService.save(); <-- another way
verify(testService, times(1)).save();
}
If you want to do an integration test, you do not mock the service, but setup an application context to inject real beans, but ordinarily use an embedded database instead of the real one.
回答2:
just change @InjectMocks to @Autowired. This fix the issue! In this case you are not mocking, you are invoking method with real data.
回答3:
As I understand, you perform post to "/tr/test" resource, but request mapping in your controller is '/payment'. Make sure you post to resource mapped in the controller.
来源:https://stackoverflow.com/questions/26508628/how-to-call-springs-service-method-from-controller-junit