一、为什么要进行单元测试
1. 提高代码质量,写出优雅的代码,在“做”之前先“想”好了
a) 实现功能正确
b) 逻辑严密
2. 减少调试时间
3. 隔离测试
二、单元测试做了什么
1. 接口功能测试:用来保证接口功能的正确性
2. 局部数据结构测试(不常用):用来保证接口中的数据结构是正确的
a) 变量有无初始值
b) 变量是否溢出
3. 边界条件测试
a) 变量没有赋值(即为NULL)
b) 变量是数值(或字符)
i. 主要边界:最小值,最大值,无穷大(对于DOUBLE等)
ii. 溢出边界(期望异常或拒绝服务):最小值-1,最大值+1
iii. 临近边界:最小值+1,最大值-1
c) 变量是字符串
i. 引用“字符变量”的边界
ii. 空字符串
iii. 对字符串长度应用“数值变量”的边界
d) 变量是集合
i. 空集合
ii. 对集合的大小应用“数值变量”的边界
iii. 调整次序:升序、降序
e) 变量有规律
i. 比如对于Math.sqrt,给出n^2-1,和n^2+1的边界
4. 所有独立执行通路测试:保证每一条代码,每个分支都经过测试
a) 代码覆盖率
i. 语句覆盖:保证每一个语句都执行到了
ii. 判定覆盖(分支覆盖):保证每一个分支都执行到
iii. 条件覆盖:保证每一个条件都覆盖到true和false(即if、while中的条件语句)
iv. 路径覆盖:保证每一个路径都覆盖到
5. 各条错误处理通路测试:保证每一个异常都经过测试
三、Junit & Spring Cloud
1. 关注点
a) 测试容器
b) 测试事务
c) 测试数据
2. 类注解
a) @RunWith(SpringRunner.class):运行器
b) @ContextConfiguration(classes=Application.class):启动容器
c) @ActiveProfiles("Single"):启动的Profiles
d) @SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT):Web测试
3. 属性注解
a) @Autowired:注入待测试对象
4. 方法注解
a) @BeforeClass:测试类启动之前
b) @AfterClass:测试类启动之后
c) @Before:每个方法测试启动前
d) @After:每个方法测试启动后
e) @Ignore:忽略的方法
f) @Test:待测试的方法
5. 其他
a) 慢
b) 关注结果
四、Mockito & Spring Cloud
1. 关注点
a) Mock:模拟
b) 代码覆盖
c) 简化测试环境
d) 异常路径(可模拟异常行为)
e) 与其他模块,系统(分布式或其他)有交互.隔绝其他异常,关注被测试模块
f) 多线程(不了解)
2. Mock关键点
a) 测试数据
b) 预期结果
c) 验证结果
3. 使用Mockito进行Mock测试
a) 类注解
i. @RunWith(MockitoJUnitRunner.class)
b) 属性注解
i. @Mock:模拟对象
ii. @InjectMocks:待测试对象
c) 方法注解
i. @BeforeClass:测试类启动之前
ii. @AfterClass:测试类启动之后
iii. @Before:每个方法测试启动前
iv. @After:每个方法测试启动后
v. @Ignore:忽略的方法
vi. @Test:待测试的方法
d) 测试过程常用方法
i. mock(Object):模拟一个对象
ii. any*:如anyInt, Mock随便给一个值
iii. When()..thenReturn()..thenAnswer()..thenCallRealMethod()..thenThrow(): 打桩,模拟过程时输入,输出
iv. doNothing().when(obj).notify() : 无返回值打桩
v. verify() : 验证Mock对象是否被正确调用
1. never():没有被调用
2. atLeast(N) & atLeastOnce() : 至少被调用
3. atMost() : 最多被调用
4. times(N) : 被调用过N次
vi. ArgumentCaptor : 参数传递是否正确,观察Mock对象参数
vii. Spy : 修改Mock对象方法行为
viii. Assert : 验证最终结果
4. 优点
a) 提前创建测试; TDD(测试驱动开发)
b) 团队可以并行工作
c) 你可以创建一个验证或者演示程序
d) 为无法访问的资源编写测试
e) Mock 可以交给用户