文章目录
本文主要针对目前单元测试可能存在的现象,来探讨一些解决方案
1 单元测试的好处
- 保证项目质量
- 降低项目成本(项目改动越频繁降低的成本越多)
- 降低开发过程中需求变更带来的代码改动成本
- 降低测试人员的工作
- 降低后期先维护成本
- 降低后期项目重构成本
- 增加自信
- 优质的单元测试可以使得开发人员对项目质量非常放心
- 功能迭代、重构时也没有后顾之忧
- 他人也会对你的项目有信心
- 提高设计能力:如果你觉得哪个方法难以测试,肯定(99%)是你设计有问题
2 单元测试质量不高的原因
-
排期少,写单元测试耗时太长
-
单元测试运行耗时太长:导致大量 ignore
-
单元测试依赖本地服务(redis、数据库等)导致线上测试不通过:导致大量 ignore
-
单元测试没有强制要求
3 本文目标
- 加强单元测试认知(不在于语言和测试框架)
- 使单元测试变得简单
- 在相同时间内,写出更好、覆盖率更高、更优质的测试用例
- 减少单元测试运行时间
4 单元测试内容
4.1 单元测试的定义与目的
- 定义: 是针对软件设计的最小单元,做正确性检验的测试工作
- 目的: 证明最小单元的行为符合开发者预期
4.2 集成测试的定义与目的
-
定义: 对多个最小单元组成的集成模块的正确性检验测试工作
-
目的: 证明集成模块的行为符合开发者预期
4.3 单元测试场景
- 添加功能:保证其他模块正确,避免引入新的bug
- 修改 bug:好的单元测试可以避免引入新的 bug
- 回归测试
- 重构:检验重构是否正确
4.4 单元测试的原则
- 独立性
- 测试方法能不调用其他测试方法
- 测试方法之间操作的资源隔离
- 不依赖方法间的执行顺序(完全认为所有方法时并行执行的)
- 不依赖其他方法
- 可重复:重复执行结果一致
4.5 单元测试组成
- 测试标识(如:@Test)、测试条件(如:@Ingore)、测试前后动作(如:@Before、@After)
- mock:模拟测试方法中可能依赖的对象
- stubbing:为 mock 出来的对象打桩(控制模拟对象的行为)
- assert:断言,没有断言的测试不是测试
5 如何使单元测试变得简单
5.1 单元测试现象
- 太多重复的测试(controller、service、mapper 层都进行了启动 spring 测试)
- 运行时间太长(主要是spring启动时间)
- 测试不完整(只测正常流程,因为测所有参数非常麻烦)
- 总结:对单元测试的认知不够,没有形成一个好的套路
5.2 思路
- 使测试方法之间独立
- 较少测试方法的依赖
- 识别有效参数
- 识别等价类与边界值
5.3 测试方法之间独立
- 保证方法独立,解决数据冲突后顾之忧
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseApplicationTest.class)
@ActiveProfiles("unit_test")
@Rollback //此注解保证了事务方法执行后都会进行回滚操作,保证了方法之间的数据隔离
public class MapperTest {
@Test
@Transactional //开启事务,保证数据隔离
public void selectByName1() throws Exception {
}
}
5.4 减少测试方法依赖
- 测试方法中包含的其它方法调用,是测试复杂度的核心因素之一
@Service
public class UserService implements UserApi {
@Autowired
UserInfoService userInfoService;
@Override
public UserDTO getOrderListDemo(UserInfoRequest req, String site, String name, List<String> names){
if (req == null) {