深入JUnit4

来源:互联网 发布:健身器材 知乎 编辑:程序博客网 时间:2024/05/17 12:54

JUnit简介

JUnit是一个Java语言的单元测试框架,也是程序员使用的白盒测试框架。
JUnit4在JUnit3的基础上引入了JDK1.5的注解特性,同时兼容JUnit3的测试用例写法,本文只介绍JUnit4,尤其是平常用得很少的一些高级用法。

基础注解

  • @Test测试方法
  • @Ignore被忽略的测试方法
  • @Before每一个测试方法之前执行一次的方法
  • @After每一个测试方法之后执行一次的方法
  • @BeforeClass所有测试方法之前执行一次,方法必须为static修饰
  • @AfterClass所有测试方法之后执行一次,方法必须为static修饰

以上注解,只可作用于方法,而且方法必须是public void修饰。

基本上了解到以上注解,就可以使用junit4进行编写测试用例了,简单例子如下:

package jtest.samples.money;/** *  * @author guor * @version 2014/6/3 */public class Money {private int fAmount;/** * Constructs a money from the given amount */public Money(int amount) {fAmount = amount;}public int amount() {return fAmount;}}
package jtest.samples.money;import org.junit.After;import org.junit.Assert;import org.junit.Before;import org.junit.Ignore;import org.junit.Test;/** * @author guor * @version 2014/6/3 */public class MoneyTest {    private Money money;        @Before    public void setUp() throws Exception {        money = new Money(26);    }    @After    public void tearDown() throws Exception {        money = null;    }    @Test    public void testSimplify1() {        Assert.assertEquals(26, money.amount());    }    @Test    @Ignore    public void testSimplify2() {        Assert.assertEquals(26, money.amount());    }}

正如上述示例,基本上掌握好以上注解,就可以编写普通的测试用例了。下面我将介绍JUnit4的一些高级用法。

高级特性

@Rule注解

@Rule注解用于标记属性或方法,其必须为public,不能为static,而且属性的类型和方法的返回值必须是org.junit.rules.TestRule或org.junit.rules.MethodRule的子类。

有了@Rule属性之后,测试用例执行的顺序为:@BeforeClass -> TestRule/MethodRule -> @Before -> @Test -> @After

从执行流程中可以看出,@Rule相当于对测试用例进行了一次拦截处理,知道这点之后,建议看看junit4为我们提供的TestRule四种默认实现,分别是ExternalResource(资源处理型)、Verifier(通知型)、TestWatcher(监听型)、Timeout(超时型),这里面也基本上就是设计模式里面的模版方法模式的应用,实际使用时,我们只需要对这四种实现进行实现即可。

下面给出Timeout的使用方法

package jtest.samples.money;import org.junit.After;import org.junit.Assert;import org.junit.Before;import org.junit.Rule;import org.junit.Test;import org.junit.rules.TestRule;import org.junit.rules.Timeout;/** * @author guor * @version 2014/6/3 */public class MoneyTest {    private Money money;    @Rule    public TestRule globalTimeout = new Timeout(1000); // 所有测试方法执行时间不能超过1s    @Before    public void setUp() throws Exception {        money = new Money(26);    }    @After    public void tearDown() throws Exception {        money = null;    }    @Test    public void testSimplify() {        Assert.assertEquals(26, money.amount());    }}

例子中,定义了全局变量globalTimeout,并用@Rule注解标记,则所有的测试方法执行时间不能超过1s,否则程序会自动退出。

@RunWith注解

首先要知道JUnit中所有的测试用例,其最终都是由Runner调用运行的,默认的是BlockJUnit4ClassRunner,如果需要自定义一个Runner,除了需要继承Runner抽象类实现其抽象方法之外,还需要提供一个带参构造函数,其参数为Class,默认的Runner实现保证了测试类在测试用例执行之前初始化,而且不会持有这个测试类的对象,以确保JVM的垃圾回收机制正确执行,自定义Runner时,尤其需要注意这点,一般我们选择继承BlockJUnit4ClassRunner就可以了。

现在假设有测试需求,需要指定某些测试方法的执行次数,实现如下:

1. 自定义注解RunTimes

package jtest.samples;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 执行次数注解,作用在方法上,用于决定测试方法执行次数 * @author guor * @version 2014/6/3 */@Retention(RetentionPolicy.RUNTIME)@Target({ ElementType.METHOD })public @interface RunTimes {/** * 测试用例执行次数,默认为1 *  * @return */int value() default 1;}

2. 自定义Runner,处理RunTimes注解

package jtest.samples;import org.junit.runner.notification.RunNotifier;import org.junit.runners.BlockJUnit4ClassRunner;import org.junit.runners.model.FrameworkMethod;import org.junit.runners.model.InitializationError;/** * 自定义Runner,主要处理RunTimes注解的逻辑 * @author guor * @version 2014/6/3 */public class CustomRunner extends BlockJUnit4ClassRunner {public CustomRunner(Class<?> klass) throws InitializationError {super(klass);}@Overrideprotected void runChild(FrameworkMethod method, RunNotifier notifier) {RunTimes annotation = method.getAnnotation(RunTimes.class);if (annotation == null) {super.runChild(method, notifier);} else {int runTimes = annotation.value();for (int i = 0; i < runTimes; i++) {super.runChild(method, notifier);}}}}

3. 简单测试用例

package jtest.samples;import org.junit.Test;import org.junit.runner.RunWith;/** * 简单测试用例 *  * @author guor * @version 2014/6/3 */@RunWith(CustomRunner.class)public class SimpleTest {@Test@RunTimes(10)// 注解说明该测试方法执行次数public void testSimplify() {System.out.println(System.currentTimeMillis());}}

2 0
原创粉丝点击