My goal is to migrate a Spring Boot application previously developed with Spring Boot 1.3 to the newest Spring Boot version 1.4. The application consists of several maven modules and only one of them contains class annotated with @SpringBootApplication.
One part of migration is to use @WebMvcTest annotation to efficiently test controllers, and here I get an issue.
Consider an example application from Spring Boot github page. @WebMvcTest annotation works perfectly, because, as far as I understand (after I did several tests), there is a class in the main package annotated with @SpringBootApplication. Note that I follow the same concept as shown in the example above for my own @WebMvcTest tests.
The only difference I see that in my application, controller classes are located in a separate maven module (without @SpringBootApplication annotated class), but with @Configuration and SpringBootConfiguration configurations. If I do not annotate any class with @SpringBootApplication I always get an assertion while testing controller. My assertion is the same as when SampleTestApplication class in the example above modified to have only @EnableAutoConfiguration and @SpringBootConfiguration annotations (@SpringBootApplication is not present):
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)
Run Code Online (Sandbox Code Playgroud)
How should I deal with that? Should I always have class annotated with @SpringBootApplication in order to run @WebMvcTest tests?
EDIT 1: I did a small maven project with 2 modules and a minimal configuration. It is here. Now, I get NoSuchBeanDefinitionException exception for repository defined in another module. If I configure "full" @SpringBootApplication - everything is fine.
EDIT 2: I modified small test project from EDIT 1 to give an original issue. I was playing with different annotations and added @ComponentScan on configuration class, because I suspected that beans are not registered properly. However, I expect that only @Controller bean (defined in @WebMvcTest(...class)) shall be registered based on magic behind @WebMvcTest behaviour.
EDIT 3: Spring Boot project issue.
简短的回答:我相信是这样。
长答案:
我相信@WebMvcTest需要找到 SpringBootApplication 配置,因为它WebMvcTest的唯一目的是帮助简化测试(SpringBootApplication宁愿尝试加载整个世界)。
在您的特定情况下,由于您的非测试包中没有任何包,我相信它还会找到 SampleTestConfiguration ,该配置带有注释@ScanPackages并以某种方式加载每个 bean。
在中添加以下内容 src/main/java/sample/test
@SpringBootApplication
public class SampleTestConfiguration {
}
Run Code Online (Sandbox Code Playgroud)
并将您的测试更改为:
@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
}
}
}
Run Code Online (Sandbox Code Playgroud)
@WebMvcTest找到SpringBootApplication,然后仅加载有限数量的 bean(请参阅文档):
@WebMvcTest 将自动配置 Spring MVC 基础结构并将扫描的 bean 限制为 @Controller、@ControllerAdvice、@JsonComponent、Filter、WebMvcConfigurer 和 HandlerMethodArgumentResolver。使用此注释时不会扫描常规 @Component bean。
WebMvcTestrequires SpringBootApplication:WebMvcTest继承了很多AutoConfiguration,所以需要SpringBoot来加载它们。然后它会禁用许多其他自动配置,并且您的控制器变得易于测试。
使用的全部意义WebMvcTest在于当您有一个SpringBootApplication并且您希望通过禁用除控制器之外的所有 bean 来简化测试。如果您没有 SpringBootApplication,那为什么还要使用 WebMvcTest?
| 归档时间: |
|
| 查看次数: |
3064 次 |
| 最近记录: |