java的单元测试原理
原理描述
java进程的启动依赖于唯一的main函数,java中的junit采用插件隐藏main函数的方式,我们右键运行某测试用例。其本质上传入的是测试用例的路径。而插件启动的main函数通过args去接受传入的用例路径,并解析出测试用例的前后执行方法(包括一些注解),并对具体的方法进行排序,最后采用多线程submit任务,从而进行测试用例的执行。在idea中选中包路径运行整个包下的测试用例,相当于启动了若干个runner任务。
@RunWith是什么?
不同的测试工具有不同的单测规则,原理基本如上段所述。我们比较常用的单测框架有junit,而且junit的不同版本其语法规则也不一样。比如junit3,junit4,junit5.不能混用的原因就是他们有不同的语法解析过程。用的不对等价于白用。
所以@RunWith表示junit版本比较多的情况下指定运行的junit版本。我们开发中比较常见的有@RunWith(SpringRunner.class)、@RunWith(SpringJUnit4ClassRunner.class)、@RunWith(SpringJUnit5ClassRunner.class)等。在不指定@RunWith的时候会创建一个默认简单的单测构造器,然后直接去执行测试用例。@RunWith的作用是为了解决版本问题。但是有时候没有版本问题就不需要添加这个注解。
单元测试和Spring的整合
因为简单的测试用例没办法针对Spring的函数进行调用,尤其是依赖反转、aop这些能力。所以需要将spring的能力接纳过来。因为spring核心的是启动了一个start()方法,所以我们可以绕过spring项目的main函数而直接去走start方法,然后做一些变动就可以将spring提供的能力整合到单元测试框架中。
什么是行为驱动测试
我的理解是单元测试只能针对具体的函数或者接口,但是我们的业务往往是相互连接,而且错综复杂的。逐个对函数进行单测只能保证单个函数没有问题,但当方法组合成业务的时候,很难保证系统整体上没有问题。
比如:
对于接口 A、B、C.......的随机组合,按不同顺序去请求接口,那么系统是否会产生一些出乎意料的结果?
所以,行为驱动测试是以业务人员的视角进行测试。
如何实现BDD
市面上比较常用的BDD框架是cucumber 。
先做一个demo尝尝鲜!
1、idea安装cucumber插件。(单元测试的main主函数从此触发)
引入maven依赖
代码语言:javascript复制核心解析包
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.1.0</version>
</dependency>
<!--整合spring的包
https://mvnrepository.com/artifact/io.cucumber/cucumber-spring -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>6.9.0</version>
</dependency>
单测包
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.9.0</version>
<scope>test</scope>
</dependency>
2、编写feature脚本
cumuber默认的feature脚本路径是testresources目录,如果没有,我们创建resources目录,我们创建一个简单的add.feature
这时候,我们的测试用例后边都是白色的背景色。我们需要创建相关的java文件。我们alt enter。进行创建。
随便写点,括号表示传入的参数。
3、编写测试用例
4、执行单测
右键我们的feature文件
5、与spring的整合
在和spring整合这块,cumuber提供了cumuber-spring的jar包。只需要我们在写代码的时候添加上注解@CucumberContextConfiguration即可。
BDD存在的问题
comuber不能mock,因为所采用的junit不是同一junit。
就到这里吧,冬天来了,注意不要感冒流鼻涕!