SpringBoot @WebMvcTest 在与 @SpringBootApplication一起使用时@Compon



我正在使用SpringBoot 2.3.3.RELEASE,我有以下Web控制器和服务。

myapp
- controllers
- ProductController
- OrderController
- services
- ProductService
- OrderService

ProductController只取决于ProductServiceOrderController只取决于OrderService

以下是我的 SpringBoot 主入口点类:

package com.sivalabs.myapp;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

我有一个用于测试ProductController@WebMvcTest控制器,如下所示:

@WebMvcTest(controllers = ProductController.class)
class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ProductService productService;

//some tests
}

使用此配置,一切都很好。

我正在尝试使用一些带有不同包名称的 Spring 组件的外部库,所以我想覆盖@ComponentScan如下:

package com.sivalabs.myapp;
import com.somelib.BeanConfig;
@SpringBootApplication
@ComponentScan(basePackageClasses = {Application.class, BeanConfig.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

当我在主入口点类中包含@ComponentScan并运行基于@WebMvcTest的测试ProductControllerTest时,除了ProductServiceSpringBoot 还尝试初始化OrderService。理想情况下,ProductControllerTest不应该加载OrderService因为ProductController不依赖于OrderService。这是一个错误吗?

解决方法:

  1. 如果我使用@ComponentScan元注释的使用方式@SpringBootApplication并包括basePackageClasses它工作正常。
package com.sivalabs.myapp;
@SpringBootApplication
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) },
basePackageClasses = {Application.class, BeanConfig.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
  1. 如果我添加另一个配置类并在该类上添加@ComponentScan,则无需在主入口点类上添加@ComponentScan,然后它工作正常。
package com.sivalabs.myapp.config;
@Configuration
@ComponentScan(basePackageClasses = {BeanConfig.class})
public class AppConfig {
}

是组件扫描过程中的错误还是按预期工作?

它按预期工作。 @SpringBootAplication已经@ComponentScan过滤器,并在 workaroud #1 中重新声明它没有意义,对吧?

原始代码的问题在于@ComponentScan覆盖排除在注释内部应用的过滤器@SpringBootApplocation。而且不排除内容,因此当@WebMvc尝试使用过滤器请求部分上下文时,它会失败,并且会加载整个上下文。

只需检查每个场景中针对上下文初始化了哪些 bean。并坚持使用解决方案 2。@SpringBootTest将扫描应用程序类所在的包,任何其他包都应按配置进行扫描。那更脆弱吧?:)

最新更新