【Springboot】复杂单元测试启动类-只测试OpenFeign以及只测试Spring Data JPA
复杂单元测试启动类-只测试OpenFeign以及只测试Spring Data JPA
背景
随着springboot应用工程规模越来越大,集成了较多的自动配置的程序,例如 Spring Data JPA, Spring Cloud OpenFeign, Apache Dubbo
有时会需要在本地运行测试,但要么因为数据库无法在办公网络环境连接,要么注册中心无法连接,这就导致本地完全无法运行。
需求
运行 SpringBoot 单元测试,只测试 OpenFeign 的部分,不启动数据库,不启动 Dubbo。
方法
- SpringBoot 通过注解和元注解进行自动配置,可以通过某些注解例如 @EnableAutoConfiguration 的 exclude 进行排除。
- Spring原生注解 @ComponentScan 有包扫描路径可以配置,也有 Filter 进行精确控制扫描范围,指定扫描的类型,正则表达式等
思路
阻止Dubbo启动
找出Dubbo的自动配置类,规则: DubboXXXAutoConfiguration
过程中,如果有遗漏就继续追加
@EnableAutoConfiguration(exclude = {
DubboAutoConfiguration.class,
DubboRelaxedBindingAutoConfiguration.class,
DubboEndpointMetadataAutoConfiguration.class,
DubboEndpointAnnotationAutoConfiguration.class,
DubboMetricsAutoConfiguration.class
})
声明包扫描路径为OpenFeign
Feign自己的注解:EnableFeignClients
@EnableFeignClients(basePackages = "com.slankka.cloud.rpc.feign")
复杂ComponentScan注解
- 声明 OpenFeign 的 Client 所在包路径 basePackages
- 声明 includeFilters
- 通过注册限定FeignClient注解进行过滤
- 通过正则表达式限定其他的某些额外需要的类(这些类受限于 basePackages)
- 关闭 useDefaultFilters,防止自动扫描 @Components 注解
有了以上严格规则限定,即便和这个类放在同一个包的其他启动入口,也不会意外启动
//包路径限定 "com.slankka.cloud.rpc.feign", "com.slankka.cloud.server.listener"}
//注解限定 FilterType.ANNOTATION, classes = {FeignClient.class}),
//正则表达式限定 FilterType.REGEX, pattern = {".*ContextHolder"})
public class TestOpenFeign {
}
SpringBootTest 注解
- @SpringBootConfiguration将上述注解放在一起作为应用类 TestOpenFeign.class
@ComponentScan(basePackages = {"com.slankka.cloud.rpc.feign", "com.slankka.cloud.server.listener"},
includeFilters =
{@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {FeignClient.class}),
@ComponentScan.Filter(type = FilterType.REGEX, pattern = {".*ContextHolder"})
}
, useDefaultFilters = false
)
@EnableFeignClients(basePackages = "com.slankka.cloud.rpc.feign")
@EnableAutoConfiguration(exclude...)
@SpringBootConfiguration
public class TestOpenFeign {
}
- 新写一个 @SpringBootTest 作为入口
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
@SpringBootTest(classes= TestOpenFeign.class)
public class OpenFeignLauncher {
}
另外,不用SpringBootTest启动类也可以,直接把TestOpenFeign当作正常类也可以
手动初始化ApplicationContext,不使用 SpringBootTest
public static ConfigurableApplicationContext init(String[] args) {
closeDubboLogo();
SpringApplication local = new SpringApplicationBuilder()
.web(WebApplicationType.NONE)
.sources(TestOpenFeign.class)
.build();
return local.run(args);
}
public static void main(String[] args) {
ConfigurableApplicationContext init = init(args);
// run test methods
init.close();
}
扩展需求
如何在上述基础上,只测试 JPA 数据库
- 在包扫描路径中追加 JpaConfig 所在包
- 通过正则表达式限定 JpaConfig 类,防止初始化其他 @Configuration 类。
@ComponentScan( basePackages = {
"com.slankka.cloud.config", //JPAConfig 所在包
"com.slankka.cloud.rpc.feign"
//...
includeFilters... = {pattern = { ".*JpaConfig" }} //JpaConfig也要被识别
})
@EnableFeignClients(basePackages = "com.slankka.cloud.rpc.feign")
@EnableAutoConfiguration(exclude...)
@SpringBootApplication(scanBasePackageClasses = {JpaConfig.class})
public class TestOpenFeignAndJPA {
}
Configuring base package for component scan in Spring boot test