前一阵大佬要求给项目加上JunitTestCase,并要求主要功能覆盖率达90%+,由于之前没有写过,所以也是摸着石头过河,走一步,趟一步。
现在终于空下来了,回顾一下,做一些简单的备注。
啥是单元测试?
顾名思义,单元测试就是对一个功能单元的测试。
单元测试作为测试驱动开发的手段,可以有效的在开发阶段,避免很多bug,节约后续QA进行测试的时间。
在代码中,方法要尽可能写的简洁,功能要尽可能单一,这样在进行单元测试时,可以不受其他方法或其他依赖的干扰。
由于我们是在代码功能完成后才开始补单元测试,在补的过程中,遇到过比较复杂的方法,里面掺杂着很多不同的功能,并非是一个统一的功能,因为在写测试用例时,非常难写,需要mock很多。 而且由于方法内功能过多,不够单一,导致最后单元测试写完基本不具有参考价值,因为其中很多逻辑处理部分都使用了mock。
突然想起郭冬临的小品里的一句话:用谎言去验证谎言得到的永远是谎言。(暴露年龄了。。。)
单元测试的准备工作
在条件允许的情况下,最好是先写测试用例,再根据测试用例去开发功能。然后再根据测试用例去检测每一个功能是否正常。
如果没有条件,代码已经写完,那最好在写单元测试之前,先将代码重构,尽可能的使要测试的方法功能单一。
JUnit5
JUnit 5 is the next generation of JUnit. The goal is to create an up-to-date foundation for developer-side testing on the JVM. This includes focusing on Java 8 and above, as well as enabling many different styles of testing.
JUnit 5是下一代JUnit。目标是为JVM上的开发人员端测试创建最新的基础。这包括关注Java 8及更高版本,以及启用许多不同的测试样式。
Mockito
Mockito 这个工具的主要功能,用来模拟一切需要模拟的对象,方法,返回值,参数等等。 所有与当前测试方法无关的依赖,都可以使用Mockito来模拟。
例子
class Calculate {
private API api;
public int Sum1(int a, int b){
return a+b;
}
public int Sum2(int a){
int b = api.getB(); // 外部接口
return a+b;
}
}
class CalculateTest{
@InjectMocks // mock一个测试对象
private Calculate calculate;
@Mock // 使用mock注解标注,在运行时会自动将一个虚拟的api注入进calculate
private API api;
@Test
void testSum1(){
int a = 1;
int b = 2;
int testResult = calculate.Sum1(a,b);
Assertions.assertTrue(testResult == 3);
}
@Test
void testSum2(){
int a = 1;
Mockito.when(api.getB()).thenReturn(10); // 这一步用来模拟依赖接口的返回值,无需关心接口内部逻辑,因为我们的目的是测试Sum2方法的逻辑。
int testResult = calculate.Sum2(a);
Assertions.assertTrue(testResult == 11);
}
}