How to call Springs service method from controller (Junit)

此生再无相见时 提交于 2019-12-25 15:59:31

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!