spring-boot - @WebMvcTest 是否需要 @SpringBootApplication 注释?

标签 spring-boot

我的目标是将之前使用 Spring Boot 1.3 开发的 Spring Boot 应用程序迁移到最新的 Spring Boot 版本 1.4。该应用程序由几个 maven 模块组成,其中只有一个包含用 @SpringBootApplication 注释的类.

迁移的一部分是使用 @WebMvcTest注释以有效地测试 Controller ,在这里我遇到了一个问题。

考虑 example application来自 Spring Boot github 页面。 @WebMvcTest注释工作得很好,因为据我所知(在我做了几次测试之后),主包中有一个用 @SpringBootApplication 注释的类.请注意,我自己的 @WebMvcTest 遵循与上面示例中所示相同的概念。测试。

我看到的唯一区别是,在我的应用程序中, Controller 类位于单独的 maven 模块中(没有 @SpringBootApplication 注释类),但带有 @Configuration 和 SpringBootConfiguration配置。如果我不使用 @SpringBootApplication 注释任何类我在测试 Controller 时总是得到一个断言。我的断言与上面示例中的 SampleTestApplication 类修改为只有 @EnableAutoConfiguration 时相同。和 @SpringBootConfiguration注释(@SpringBootApplication 不存在):

getVehicleWhenRequestingTextShouldReturnMakeAndModel(sample.test.web.UserVehicleControllerTests)  Time elapsed: 0.013 sec  <<< FAILURE!
java.lang.AssertionError: Status expected:<200> but was:<404>
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54)
    at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81)
    at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:664)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
   at sample.test.web.UserVehicleControllerTests.getVehicleWhenRequestingTextShouldReturnMakeAndModel(UserVehicleControllerTests.java:68)

我应该如何处理?为了运行@WebMvcTest 测试,我是否应该始终使用@SpringBootApplication 注释类?

编辑 1:我做了一个带有 2 个模块和最小配置的小型 maven 项目。是here .现在,我得到另一个模块中定义的存储库的 NoSuchBeanDefinitionException 异常。如果我配置“完整”@SpringBootApplication - 一切都很好。

编辑 2:我从 EDIT 1 修改了小型测试项目以给出原始问题。我正在使用不同的注释并在配置类上添加了@ComponentScan,因为我怀疑 bean 没有正确注册。但是,我希望只有 @Controller bean(在 @WebMvcTest(...class) 中定义)应基于 @WebMvcTest 行为背后的魔法进行注册。

编辑 3:Spring Boot 项目 issue .

最佳答案

简短的回答:我相信是的。
长答案:
我相信@WebMvcTest需要从 WebMvcTest 开始查找 SpringBootApplication 配置的唯一目的是帮助简化测试(SpringBootApplication 宁愿尝试加载整个世界)。
在您的特定情况下,由于您的非测试包中没有任何内容,我相信它也会找到带有 @ScanPackages 注释的 SampleTestConfiguration并以某种方式加载每个bean。
src/main/java/sample/test 中添加以下内容

@SpringBootApplication
public class SampleTestConfiguration {

}
并将您的测试更改为:
@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private MyService ms;

    @Autowired
    private ApplicationContext context;

    @Test
    public void getDataAndExpectOkStatus() throws Exception {
        given(ms.execute("1")).willReturn(false);
        mvc.perform(get("/1/data").accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(status().isOk()).andExpect(content().string("false"));
    }

    @Test
    public void testMyControllerInAppCtx() {
        assertThat(context.getBean(MyController.class), is(not(nullValue())));
    }

    @Test
    public void testNoMyAnotherControllerInAppCtx() {
        try {
            context.getBean(MyAnotherController.class);
            fail("Bean exists");
        } catch (BeansException e) {
            // ok
        }
    }
}
@WebMvcTest找到 SpringBootApplication ,然后加载 bean 数量有限 (见 documentation):

@WebMvcTest will auto-configure the Spring MVC infrastructure and limit scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver. Regular @Component beans will not be scanned when using this annotation.

WebMvcTest需要 SpringBootApplication : WebMvcTest继承了很多AutoConfiguration,所以需要SpringBoot来加载。然后它会禁用许多其他 AutoConfiguration 并且您的 Controller 变得易于测试。
使用的全部要点WebMvcTest是当你有一个 SpringBootApplication并且您希望通过禁用除 Controller 以外的所有 bean 来简化测试。如果您没有 SpringBootApplication,那么为什么要使用 WebMvcTest 呢?

关于spring-boot - @WebMvcTest 是否需要 @SpringBootApplication 注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38890944/

相关文章:

java - Spring无法解析命令行参数

java - 如何从 spring boot 中排除 lib-provided

Spring Session table-name 属性不改变表名

mysql - 我无法生成自动递增的 Id,并且 hibernate 始终生成 1 作为 Id

java - ObjectMapper 将日期更改为字符串

Spring 启动 : how to set a common path for multiple RestControllers

带有自定义 UserDetails 实现的 java.io.NotSerializableException

Spring 正在失去与数据库的连接,并且无法恢复或重新连接

java - spring boot应用是否支持OpenJDK

java - Spring Boot MVC 测试 - MockMvc 始终为空