【问题标题】:How to call Springs service method from controller (Junit)如何从控制器(Junit)调用 Springs 服务方法
【发布时间】:2014-10-22 13:30:12
【问题描述】:

我看过example,如何使用mockito调用spring控制器。

使用 Mock 我调用 Spring MVC 控制器。 控制器调用 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;

}

问题是,我的应用程序没有调用保存方法,它没有被输入。我也没有错误。当我从 Junit 调用 save() 方法时,结果相同(我在 test() 方法中对其进行了注释)。

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

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

【问题讨论】:

  • 无法理解您的问题。 嘲笑服务。什么都不叫是正常的,你只需要验证什么叫...
  • 我想调用服务层,然后检查它是否写得好。不是吗?
  • 我有 MockMVC 因为我不想启动 Tomcat 服务器。

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


【解决方案1】:

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

  • 控制器的正确方法被触发并产生预期的结果
  • 在服务层调用正确的方法... 在模拟中

您只需配置模拟方法的返回值(如果相关),或控制调用的内容

@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,但通常使用嵌入式数据库而不是真实的。 p>

【讨论】:

  • 我明白了,我配置了返回值。但我不明白什么时候应该使用模拟的主要目的。如果我配置返回值,什么时候有好处?
  • 这就是 unit 测试的工作方式:您只使用 mocks 测试一个类,用于与它交互的所有其他对象。模拟是哑对象,您可以在给定输入时为其配置输出。这样你就不会因为另一个班级的问题而在一个班级的考试中失败。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    据我了解,您执行发布到“/tr/test”资源,但控制器中的请求映射是“/payment”。确保发布到控制器中映射的资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 2020-10-09
      相关资源
      最近更新 更多