如何从控制器调用Springs服务方法(Junit)

时间:2014-10-22 13:30:12

标签: spring spring-mvc mockito spring-test springmockito

我见过example,如何使用mockito调用spring controller。

使用Mock我调用Spring MVC控制器。 Controller调用Spring服务类。

@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
    }

好的,效果很好。我很好地称我的Spring控制器。但在Spring控制器中我有注入服务层。

@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;

}

问题是,我的应用程序没有调用save方法,它没有输入。我也没有错误。同样的结果是当我从Junit调用save()方法时(我在test()方法中对它进行了评论)。

当我调试时,我看到中断方法发生在org.mockito.internal.creation.MethodInterceptorFilter

如何解决这个问题?会发生什么?

3 个答案:

答案 0 :(得分:2)

如果您正在对控制器进行单元测试,则应该模拟服务层(您正在做什么)。在这种测试中,你只需控制:

  • 触发控制器的正确方法并产生预期的
  • 服务层中的正确方法称为... in mock

您只需配置模拟方法的返回值(如果相关),或控制所谓的

@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(...);
}

稍后验证所谓的

@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();
}

如果你想进行集成测试,你不要模拟服务,而是设置一个应用程序上下文来注入真正的bean,但通常使用嵌入式数据库而不是真正的数据库。

答案 1 :(得分:2)

只需将@InjectMocks更改为@Autowired即可。这解决了这个问题!在这种情况下,您不是在嘲笑,而是使用实际数据调用方法。

答案 2 :(得分:0)

据我所知,你执行post到“/ tr / test”资源,但是你的控制器中的请求映射是'/ payment'。确保发布到控制器中映射的资源。