【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

posted @ 2024-05-22 09:55  一杯半盏  阅读(278)  评论(0编辑  收藏  举报