当我同时使用 webAppContextSetup 时,我很难让 Mockito 和 MockMvc 一起工作。我很好奇这是否是因为我以一种他们从未想过的方式将两者混合在一起。

来源:https://github.com/zgardner/spring-boot-intro/blob/master/src/test/java/com/zgardner/springBootIntro/controller/PersonControllerTest.java

这是我正在运行的测试:

package com.zgardner.springBootIntro.controller; 
 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mock; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.support.DefaultListableBeanFactory; 
import org.springframework.boot.test.SpringApplicationConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.web.WebAppConfiguration; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.context.WebApplicationContext; 
 
import static java.lang.Math.toIntExact; 
import static org.hamcrest.Matchers.is; 
import static org.mockito.MockitoAnnotations.initMocks; 
import static org.mockito.Mockito.when; 
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; 
 
import com.zgardner.springBootIntro.Application; 
import com.zgardner.springBootIntro.service.PersonService; 
import com.zgardner.springBootIntro.model.PersonModel; 
 
@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
@WebAppConfiguration 
public class PersonControllerTest { 
 
    private MockMvc mockMvc; 
 
    @Autowired 
    private WebApplicationContext webApplicationContext; 
 
    @Autowired 
    private DefaultListableBeanFactory beanFactory; 
 
    @Mock 
    private PersonService personService; 
 
    @InjectMocks 
    private PersonController personController; 
 
    @Before 
    public void setup() { 
        initMocks(this); 
 
        // beanFactory.destroySingleton("personController"); 
        // beanFactory.registerSingleton("personController", personController); 
 
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 
    } 
 
    @Test 
    public void getPersonById() throws Exception { 
        Long id = 999L; 
        String name = "Person name"; 
 
        when(personService.findById(id)).thenReturn(new PersonModel(id, name)); 
 
        mockMvc.perform(get("/person/getPersonById/" + id)) 
            .andDo(print()) 
            .andExpect(jsonPath("$.id", is(toIntExact(id)))) 
            .andExpect(jsonPath("$.name", is(name))); 
    } 
} 

我期望当 mockMvc 执行该 HTTP 调用的模拟时,它会使用我在测试中定义的 PersonController。但是当我调试通过时,它使用的是在测试启动时由 SpringJunit4ClassRunner 创建的 PersonController。

我找到了两种方法让它工作:

  1. 注入(inject) bean 工厂,删除旧的 personController 单例,并添加我自己的。这太丑了,我不是粉丝。
  2. 使用 standaloneSetup 而不是 webAppContextSetup 连接所有内容。我可能会这样做,因为我不必接触 bean 工厂。

以下是我发现的一些不同的文章,它们在一定程度上涉及到这个主题:

想法?

请您参考如下方法:

您可能对 new testing features 感兴趣即将在 Spring Boot 1.4 中出现(特别是新的 @MockBean 注释)。这sample展示了如何通过 Controller 测试模拟和使用服务。


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!