【Springboot】玩转复杂单元测试启动类-只测试数据访问层(JPA+Mybatis) 和服务层 以及Junit和TestNG
上一篇文章写了一个最复杂的 SpringBootTest启动类,定制化程序奇高,然而有时候仅测试JPA是不够的。
【SpringBoot】复杂单元测试启动类-只测试OpenFeign以及只测试Spring Data JPA
说明
本篇文章更好的解决了类型扫描的问题,避免手写复杂的ComponentScan表达式,以及避免使用 @SpringBootApplication 启动类。
启动类
需求:
- 测试Spring Data JPA
- 测试Mybatis
- 从容器中获得 ObjectMapper
- 测试单独的 Service
- 使用TestNG或者使用Junit
- 阻止Dubbo、Kafka、ElasticSearch 等中间件启动
- 使用 application-test.properties 配置
- 使用 Apollo Config 自动配置
基本结构
@SpringBootTest(classes = {JpaConfig.class},
webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test")
@EnableAutoConfiguration(exclude = {
DubboAutoConfiguration.class,
DubboRelaxedBindingAutoConfiguration.class,
KafkaAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class,
ReactiveElasticsearchRepositoriesAutoConfiguration.class,
ReactiveElasticsearchRestClientAutoConfiguration.class
})
public class DaoTest {
//...
}
说明
基本测试注解:
- @SpringBootTest 声明了 webEnvironment,以及需要扫描的配置类,而不是整个包路径遍历扫描
- @ActiveProfiles 声明使用的Profile,对应配置文件 application-test.properties
- @EnableAutoConfiguration
其中 JpaConfig.class 是启动 JPA的配置类,该类主要声明 Datasource,以及使用 configurationProperties,从而将Apollo配置中心、配置文件数据源扫描到上下文中。
Mybatis
启动Mybatis的Mapper接口扫描:
- 其中 @AutoConfigureMybatis 注解 和 @SpringBootTest 兼容。
- 其中 @AutoConfigureTestDatabase 注解 声明使用真实的数据库,而不是H2。
- 其中 @MapperScan声明了 dao所在包位置,防止因为启动类包路径不在 dao上层以及dao的包路径存在特殊的位置,而扫描不到Mapper接口的情况。
@MapperScan("com.slankka.company.dao.mapper")
@AutoConfigureMybatis
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
或者通过如下方式制定,并在 DaoTest 类上 Import
//..
@Import(MappersConfig.class)
//..
public class DaoTest {
//...
}
@TestConfiguration
@ComponentScan("com.slankka.company.dao.mapstruct")
public class MappersConfig {
}
随意指定需要扫描的 Service
- 方法一:直接在 @SpringBootTest 上声明 classes
- 方法二:使用单独的类并@Import
例如
@AutoConfigureJsonTesters
@Import({FrameworkServiceImpl.class})
public class EnableFrameworkServiceTestBundle {
}
说明
*不需要任何方法,空类即可,好处是可以分门别类,同时如果待测试的 ServiceImpl 实现类,还缺少某个Bean,同样可以 @Import。
//..
@SpringBootTest(classes = { JpaConfig.class, EnableFrameworkServiceTestBundle.class })
//..
public class DaoTest {
//...
}
使用容器中的 ObjectMapper
@AutoConfigureJsonTesters
- @AutoConfigureJsonTesters 的作用之一,是让 spring-boot-test 初始化JSON有关的自动配置类:例如这个注解会导致 JacksonAutoConfiguration 启动,因此容器中就有了ObjectMapper
原理
@ImportAutoConfiguration
@PropertyMapping("spring.test.jsontesters")
public @interface AutoConfigureJsonTesters {
/**
* If {@link BasicJsonTester}, {@link JacksonTester}, {@link JsonbTester} and
* {@link GsonTester} beans should be registered. Defaults to {@code true}.
* @return if tester support is enabled
*/
boolean enabled() default true;
}
其中 ImportAutoConfiguration 导致下方的类型初个自动装备
# AutoConfigureJsonTesters auto-configuration imports
org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration
TestNg 还是 Junit
TestNg
TestNg 的启动类直接改成:
@SpringBootTest(classes = {JpaConfig.class},
webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test")
public class DaoTest extends AbstractTestNGSpringContextTests {
//...
}
JUnit
默认就是JUnit