Java单元测试和集成测试实践经验
-
-
-
-
-
-
写在前面的碎碎念
- 单元测试,集成测试,TDD(测试驱动开发)的重要性,开发和团队都在提。但却很难落地,原因无非,人的惰性和项目管理问题。
- 个人要从普通到卓越,团队要从作坊到大厂,单元测试和集成测试,TDD,是必不可少的。优秀的开源项目和大厂的核心项目,都很好实践了TDD。
- TDD,需要转变观念:测试不是测试人员的事儿,开发需要对代码负责,写的代码是可测试的。TDD是一种更严谨的编程思想,能减轻开发维护代码的负担,为后续持续优化提供最起码的保证。单元测试和集成测试,能让开发人员在后续功能开发和重构优化更有信心,减少错误。
- 单元测试和集成测试,是软件开发最基础的保障手段。更多测试的手段有,自动化测试,流量重放和对比测试等。
相关书籍和文章
书籍
-
这两本书籍是关于重构和如何写整洁的书籍。但是书中,有阐述单元测试的重要性,和如何写测试。非常值得一读。
-
书中有很多关于TDD和Java测试框架的介绍,可以作为入门级的读物
文章
- Gradle 配置Test的官方介绍 实践单元测试和集成测试,工程构建使用的Gradle
- Gradle 配置Jacoco的官方介绍 测试用例,需要有测试覆盖度检查,才能保证测试用例真正覆盖了代码逻辑
- modern-best-practices-testing-java 非常棒的一篇文章
- Focus on Integration Tests Instead of Mock-Based Tests 为什么和怎么做集成测试
- Don’t use In-Memory Databases (H2, Fongo) for Tests 为何放弃内存数据库作为测试依赖
- Spring Testing 如何在Spring使用Unit Testing,Integration Testing和更多的测试学习资料
- Testcontainers 使用容器化技术,简化测试依赖的问题,让测试更准确和高效
- Wiremock 强大的Mock Server
- Mock-server 强大的Mock Server,同Wiremock
实践经验
Gradle配置Test和Jacoco
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27test{
useJUnitPlatform() //使用JUnit
failFast=true //快速失败
// 注意:此处有条件可使用远程docker方案,避免本地机器启动container后资源不足
if (System.properties['os.name'].toString().toLowerCase().contains('win')) {
enviroment "DOCKER_HOST", "tcp://#dockerip:port#"
}
}
jacocoTestReport{
reports{
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/reports.jacocoHtml") //输出jacoco html文档
}
}
jacocoTestCoverageVerifacation{
violationRules{
rule{
element ='CLASS'
includes =['com.xxx.yyyy.package'] //覆盖度检查package
limit{
minimum=0.9 //单元覆盖度
}
}
}
}
test.finalizedBy jacocoTestReport
test.finalizedBy jacocoTestCoverageVerifacation //执行jacoco报告和覆盖度检查使用Spring Test
引入依赖
1
2
3dependencies{
implementation "org.springfamework.boot:spring-boot-starter-test" //引入 test starter
}抽象测试基类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25使用Testcontainers
为了方便使用Spring Boot Test和Testcontainers,直接使用的Playtika开发的Starter.
引入依赖
1
2
3
4
5
6dependencies{
implementatin "com.playtika.testcontaners:embedded-mysql"
implementatin "com.playtika.testcontaners:embedded-redis"
implementatin "com.playtika.testcontaners:embedded-mongodb"
implementatin "com.playtika.testcontaners:embedded-rabbitmq"
}配置文件
以mysql举例
bootstrap-test.yml
1
2
3
4emebdded:
mysql:
enabled: true
init-script-path: init_mysql.sqlapplication-test.yml
1
2
3
4
5
6spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://${embbeded.mysql.host}:${embbeded.mysql.port}/${embbeded.mysql.schema}
username: ${embbeded.mysql.user}
password: ${embbeded.mysql.password}init_msyql.sql
1
--数据库初始化脚本,Create Table 和 Insert Sql
测试用例覆盖范围
Repository
测试Repository与DB交互的逻辑
Service
测试复杂业务逻辑
Endpoint
测试协议转换和入参校验
测试框架推荐
Junit5
Junit5,特性和代码设计上,比Junit4好很多
AssertJ
断言,推荐使用AssertJ,特别是它的DSL
Easy-Random
很方便的创建和控制Random Object,摆脱手工New Object的麻烦
Awaitility
能方便的测试异步代码
Mockito
方便Mock,Spy,Verify Bean
-
-
-
-
-