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

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

考虑一下Spring Boot github页面上的example application@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)

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

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

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

编辑3:Spring Boot项目issue

最佳答案

简短的回答:我相信。
长答案:
我相信@WebMvcTest需要找到SpringBootApplication配置,因为WebMvcTest的唯一目的是帮助简化测试(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需要SpringBootApplication:WebMvcTest继承了许多自动配置,因此需要SpringBoot来加载它们。然后,它将禁用许多其他自动配置,并且您的 Controller 变得易于测试。
使用WebMvcTest的全部要点是当您拥有SpringBootApplication时,您希望通过禁用除Controllers之外的所有bean使其更简单地进行测试。如果您没有SpringBootApplication,那为什么还要使用WebMvcTest?

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

10-10 19:27