1. Junit4概述

JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。
新特性:
(1)、使用junit4.x版本进行单元测试时,不用测试类继承TestCase父类,因为,junit4.x全面引入了Annotation来执行我们编写的测试。(关于Annotation介绍请详见附件:Java注解(Annotation))
(2)、junit4.x版本,引用了注解的方式,进行单元测试;
(3)、junit4.x版本我们常用的注解:
A、@Before 注解:与junit3.x中的setUp()方法功能一样,在每个测试方法之前执行;
B、@After 注解:与junit3.x中的tearDown()方法功能一样,在每个测试方法之后执行;
C、@BeforeClass 注解:在所有方法执行之前执行;
D、@AfterClass 注解:在所有方法执行之后执行;
JUnit4的用例执行顺序是:@BeforeClass> @Before> @Test1> @After> @Before> @Test2> @After….. @AfterClass
E、@Test(timeout = xxx) 注解:设置当前测试方法在一定时间内运行完,否则返回错误;
F、@Test(expected = Exception.class) 注解:设置被测试的方法是否有异常抛出。抛出异常类型为:Exception.class;
G、@Ignore 注解:注释掉一个测试方法或一个类,被注释的方法或类,不会被执行。

2. 环境搭建

选中Project >右键Properties >Java Build Path>Libraries >Junit,如下图所示:

Junit4的应用

选择JUnit4,如下图所示:

Junit4的应用

创建一个Junit Case,New  >JUnit Test Case,如下图所示:
选择下图中的“Class Under test”可以选择要进行单元测试的类

Junit4的应用

3. 高级应用

3.1 Junit4的执行逻辑

1 Junit4Builder编译器会构造Test运行器,如BlockJUnit4ClassRunner,BlockJUnit4ClassRunner 会通过自己的构造器,把当前测试类传到runner里。
2 运行ParentRunner.run()方法,run 方法会获取测试类的Description信息,Description信息会包含测试类的信息,然后执行classBlock(RunNotifier),这个方法获取Statement信息,首先构造一个childrenInvoker,然后在Statement的evaluate()方法调用
runChildren()方法,用来真正地执行test方法,这个步骤会等到测试真正执行后开始做。现在是先获取Statement会处理三种注解,@Before,@After,@Rule,把标注这些注解的方法分别放在集合里,以便后面能够处理这些方法。
3 准备工作都做好之后,会执行步骤2里从classBlock(RunNotifier)获取到的Statement的evaluate()方法,这个方法用来对Statement来说是开了一个口,用户可以自定义Statement的方法,不过在这里,evaluate()主要是来执行步骤2调用的runChildren()方法。
4 runChildren()方法的作用是:遍历测试类的所有测试方法(getFilteredChildren),开启线程调度fScheduler,调度线程给每一个测试方法,然后执行Runnable.run()方法,让测试执行器,让测试执行器可以执行测试类的测试方法(runChild)。
5 执行测试方法首先会判断方法是否含有@Ignore注解,如果有,那么忽略它的测试。如果没有那么执行runLeaf()方法。这个方法是真正我们执行测试的开始。
6 RunLeaf(Statement, Description, RunNotifier),首先Statement是有methodBlock(FrameworkMethod)产生,FrameworkMethod 存着当前要执行的测试方法,在这个方法里,用了反射机制。这时候Junit4会构造RunRules会把Statement,
Description apply()到MethodRules, TestRule进去,也就是说,我们在外部构造的带有@Rule,@Before, @After等就在这里执行,如:
@Rule
public final TestRule testRule = new CommonRule();
此时,我们就可以在我们新构建的CommonRule类里面的apply()方法,做一些对test的预处理,比如预处理连接数据库字符串,读取方法上元数据的信息等;
7 然后就真正执行RunLeaf(Statement, Description, RunNotifier),通过传进来的参数构建EachTestNotifier,执行fireTestStarted,然后,再打开对话,statement.evaluate(),这个执行过程中,会用到InvokeMethod类,然后调用InvokeMethod.evaluate(),最后调用Method.invoke()方法真正地执行了test实体。测试开始了。
备注:就如刚所说的,真正开始测试前,我们可以用apply()进行一些处理,同样地,我们可以在apply()方法中,创建用户Statement,这样就能在evaluate()方法中,做一些操作。如执行脚本,日志等。

3.2 Runner ( 运行器 )

大家有没有想过这个问题,当你把测试代码提交给 JUnit 框架后,框架如何来运行你的代码呢?答案就是—— Runner 。在 JUnit 中有很多个 Runner ,他们负责调用你的测试代码,每一个 Runner 都有各自的特殊功能,你要根据需要选择不同的 Runner 来运行你的测试代码。可能你会觉得奇怪,前面我们写了那么多测试,并没有明确指定一个Runner 啊?这是因为 JUnit 中有一个默认 Runner ,如果你没有指定,那么系统自动使用默认 Runner 来运行你的代码。换句话说,下面两段代码含义是完全一样的:
Import  org.junit.internal.runners.TestClassRunner;
import  org.junit.runner.RunWith;
// 使用了系统默认的TestClassRunner,与下面代码完全一样 
public  class  CalculatorTest  {
...

@RunWith(TestClassRunner. class )
public   class  CalculatorTest  {
...
}
从上述例子可以看出,要想指定一个 Runner ,需要使用 @RunWith 标注,并且把你所指定的 Runner 作为参数传递给它。另外一个要注意的是, @RunWith 是用来修饰类的,而不是用来修饰函数的。只要对一个类指定了 Runner ,那么这个类中的所有函数都被这个 Runner 来调用。


 

相关文章:

  • 2021-07-20
  • 2021-10-08
  • 2022-02-12
  • 2019-06-12
  • 2021-06-13
猜你喜欢
  • 2022-12-23
  • 2021-08-14
  • 2021-06-03
  • 2022-12-23
  • 2022-12-23
  • 2021-04-11
  • 2021-12-09
相关资源
相似解决方案