使用 Trantor 进行单元测试
背景
在 Trantor 中,访问数据依赖模型元信息,即需要依赖 MetaStore 和 DataStore 两个服务分别存储元信息和协议转换以访问数据。
在此之前,我们想在一个单元测试中访问数据,需要在本地启动一套完整 trantor 环境,并且手动清理测试中产生的数据。这个操作比较繁琐,并且不符合单元测试定义,因此我们提供了单元测试特性支持。
特性
✅ Mock MetaStore,在测试过程中不依赖 MetaStore 服务。
✅ 测试完成后自动清理测试数据。
✅ 使用@ActiveModule按需注册模块,如果一个业务模块依赖了很多其他模块,在测试中我们也会注册依赖模块的模型,并在 db 里建立对应的 schema,这样会导致测试的执行速度下降,如果只需要依赖少量模块,建议注册模块。
第一个单元测试
Maven依赖
首先需要依赖一个测试 jar 包,test-framework已经集成了 spring-boot-starter-test ,不需要依赖其他测试框架,开箱即用。(若是使用插件创建的impl模块,已添加依赖)
<dependency> <groupId>io.terminus.trantor</groupId> <artifactId>test-framework</artifactId> <scope>test</scope></dependency>环境变量
✅ 启动DataStore 服务( 可以使用 trantor-cli 提供的 DataStore )
由于测试会启动一个 spring context,因此会初始化一些 bean,这些 bean 需要配置一些环境变量,比如 DS_PORT、USER_MOCK 和 ACL_MOCK 等。
Trantor 没有限制注入环境变量的方式,可以使用@SpringBootTest 或 新建一个专门用于测试的 application-test.yml,也可以用别的方式,这里以application-test.yml为例
DS_PORT: 8081USER_MOCK: trueACL_MOCK: trueDUBBO_ENABLED: false
trantor: mainModule: base声明@ActiveProfiles("test")即可:
@RunWith(TSpringRunner.class)@SpringBootTest@ActiveProfiles("test")public class UnitTest {}注册模块
如果在一个或者一组测试中,只需要依赖少量模块,建议声明注解@ActiveModule:
- 声明在类上:当前测试类只使用
@ActiveModule注册的模块资源 - 声明在方法上:当前测试方法只使用
@ActiveModule注册的模块资源
编写用例
❗️我们使用TSpringRunner 代替 spring-test 提供的 SpringRunner,其余配置与普通 spring-test 一致。
@RunWith(TSpringRunner.class) //❗️io.terminus.trantorframework.test.TSpringRunner@SpringBootTest@ActiveProfiles("test")@ActiveModule("base") //❗️模块keypublic class UnitTest { @Autowired private CompanyRepo companyRepo;
@Test //❗️@ActiveModule("base"),可以声明在方法上 public void testCreate() { Company company = companyRepo.createWithRelation(new Company()); assertThat(company.getName()).isEmpty(); }}使用插件快速创建
写单测应聚焦于单测逻辑本身,而非如何定义Trantor单测,通过插件创建单元测试可用且高效:
- 若存在
application-test.yml,插件会优先使用@ActiveProfiles(test),否则会将trantor env的环境变量自动注入@SpringBootTest。- 支持
@ActiveModule,插件会列出当前模块以及依赖模块,可多选。- 可多选测试资源,创建多个方法。

已知问题
由于 DataStore 的执行逻辑全部在服务端,逻辑又比较复杂,因此这版本测试还是依赖 DataStore,后面版本 DataStore Client 重做以后考虑支持完整的 mock。