尝试通过 AutoConfigureMockMvc 自动配置时集成测试失败

Posted

技术标签:

【中文标题】尝试通过 AutoConfigureMockMvc 自动配置时集成测试失败【英文标题】:Integration test fails when attempting to auto configure via AutoConfigureMockMvc 【发布时间】:2021-06-14 16:31:43 【问题描述】:

我正在为控制器端点编写一个简单的测试。

当我执行以下操作时它工作正常。

@SpringBootTest
@ContextConfiguration(classes = 
        HomeController.class,
        HomeControllerTest.class
)
class HomeControllerTest 

    @Autowired
    private WebApplicationContext webApplicationContext;

    private static final String URL = "/a";
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void test() throws Exception 

        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

        Request request = new Request();

        mockMvc.perform(post(URL)
                .contentType("application/json")
                .content(objectMapper.writeValueAsString(request))
                .andExpect(status().isOk());
    

但我不想创建 mockMvc 并关注 webApplicationContext。 因此,尝试改用 @AutoConfigureMockMvc,如下所示。 但这不起作用。失败并出现以下错误。

java.lang.AssertionError: 预期状态: 但原为: 预期 :200 实际 :403

我做错了什么?

我的尝试引发了上述错误。

@SpringBootTest
@AutoConfigureMockMvc // using this annotation instead
@ContextConfiguration(classes = 
        HomeController.class,
        HomeControllerTest.class
)
class HomeControllerTest 

    // wiring mockMvc instead
    // no webApplicationContext autowired
    @Autowired
    private MockMvc mockMvc;

    private static final String URL = "/a";
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void test() throws Exception 

        Request request = new Request();

        mockMvc.perform(post(URL)
                .contentType("application/json")
                .content(objectMapper.writeValueAsString(request))
                .andExpect(status().isOk());
    

【问题讨论】:

您的注释有点矛盾。你想运行一个完整的集成测试(这是@SpringBootTest 告诉我们的)但只​​加载一个控制器?您可能想要@WebMvcTest(HomeController.class) 而不是您现在拥有的。此外,您设置的不同之处在于您手动设置 MockMvc 不会启用安全性,而自动装配的 spring boot 会启用安全性(取决于 Spring Security 的可用性)。 【参考方案1】:

尝试像这个例子那样创建测试更好。

 @SpringBootTest
 @AutoConfigureMockMvc
 public class HomeControllerTest 

    private ObjectMapper mapper;
    private MyControler myController;
    private ServiceInSideConttroler service;
    add your atributes
    
    @Before
    public init()
    this.mapper = new ObjectMapperConfiguration().mapper();
    this.service = mock(ServiceInSideConttroler.class);
    this.myController = new MyController(service);
    

    @Test
    public void test() throws Exception 
          // exemple how mock reponse from any service or repository.
         when(service.findById(any(Long.class)))
          .thenReturn(Optional.of(budget));

       Object resp =  myController.save(mockben());
         ...... 
         aserts(resp)
    

记住,要使用这样的测试,不要在属性中使用@Authwired,只能在使用@service、@componet、@controller 等注释的类的构造函数中使用......也就是说,任何受控的类通过 Spring 将使用依赖注入。还 rember 断言你的回应。

【讨论】:

以上是关于尝试通过 AutoConfigureMockMvc 自动配置时集成测试失败的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 集成测试:@AutoConfigureMockMvc 和上下文缓存

使用 MockMvc 和 AutoConfigureMockMvc 测试 Spring Boot Web 应用程序时出现 LazyInitializationException 的原因是啥

@WebMVC 无法加载 ApplicationContext

没有数据库连接的 Spring Boot 测试

在每次测试之前触发 Flyway 迁移

如何使用spring集成测试按顺序运行控制器测试类