深入JUnit4

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);
	}

	@Override
	protected 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值