之前赶项目赶的昏头,被同事问起java测试类怎么写,当场卡壳,只能回去翻自己半年前写的旧代码,才慢慢捋清楚当时的写法。我习惯把测试类和业务代码分开放,源码目录放业务,测试目录专门存测试类,包结构尽量和业务代码保持一致,找起类来不会乱。
最开始图省事,直接在业务类里面加main方法做测试,运行起来倒是方便,可代码混在一起,提交代码的时候总不小心把测试打印语句一并提交到仓库,后面维护的时候一堆冗余代码,别人看我的提交记录都要皱眉。后来才反应过来,单独新建测试类,用测试框架会干净很多,不用反复删打印代码。
新建测试类的时候,类名一般就在被测试类名字后面加Test,比如有一个UserService,对应的测试类就叫UserServiceTest。类里面写测试方法,方法名不用遵守普通业务方法的命名习惯,尽量写直白一点,一眼能看懂测的是什么场景,比如testUserLoginSuccess,而不是随便写个test1。
引入JUnit5之后,测试方法上面加@Test注解就行,不用写main。方法本身返回void,不需要参数。测试逻辑就是先创建被测试对象,准备好入参,调用目标方法,然后断言结果是否符合预期。当时我写的例子,就是写一个简单的工具类,计算两个数字相加,测试类里构造入参,调用add方法,再用assertEquals对比预期值和实际返回值。断言不通过的时候,控制台会直接抛出提示,告诉你预期是什么,实际拿到的是什么,比自己写System.out打印然后肉眼判断靠谱不少。
这只是我的个人感受,不是标准答案。项目不一样,团队规范不一样,有的人会用Mockito做依赖mock,处理有外部依赖的类,我那个小项目没用到复杂依赖,就只写了基础断言,够用就行。
有段时间分不清测试类的访问修饰符,试过把测试方法写成private,结果运行的时候,测试框架识别不到这个方法,跑不起来,折腾好久才搞明白,测试方法得是public,或者用JUnit5的时候不加修饰符也可以,private方法会直接被忽略,不会执行。
还有一个容易忽略的小点,测试类不用打包上线,所以依赖只需要设置成测试范围,maven里面scope写test,打包的时候不会把JUnit的依赖打进jar包,不会增加包体积。最开始不懂这个,依赖范围没限制,打包出来的包莫名变大,排查了好一阵才找到原因。
写测试的时候不用追求全覆盖,我当时只优先测分支里容易出错的场景,正常流程,参数为空,参数超出范围这几种,那些简单get、set方法就没额外写测试,浪费时间。有些团队要求高,会要求更高覆盖率,那就得跟着团队的要求调整,不能拿我这套直接套到所有项目。
写完之后,直接在IDE里点测试类或者单个测试方法,就能单独运行,不用启动整个项目。这点比启动服务、调用接口方便太多,修改代码之后,一键跑一遍测试,快速确认改动有没有破坏原有逻辑。
那次项目交付之后,旧的测试文件就留在项目仓库里,后续接手的人,改这个工具类的时候,会顺手跑一遍这些测试,不会轻易把原有逻辑改崩。