博主推荐文章:http://www.testclass.net/junit
一个JUnit Rule就是一个实现了TestRule的类,这些类的作用类似于 @Before
、@After
,是用来在每个测试方法的执行前后执行一些代码的一个方法。 那为什么不直接用这些 @Before
、@After
呢?这是因为它们都只能作用于一个类,如果同一个setup需要在两个类里面同时使用,那么你就要在两个测试类里面定义相同的@Before方法,然后里面写相同的代码,这就造成了代码重复。
此外,JUnit Rule还能做一些 @Before
、@After
这些注解做不到的事情,那就是他们可以动态的获取将要运行的测试类、测试方法的信息。
使用框架自带的Rule
除了增加Rule特性,新版JUnit还添加了很多核心Rule
- TemporaryFolder:测试可以创建文件与目录并且会在测试运行结束后将其删除。这对于那些与文件系统打交道且独立运行的测试来说很有用。
- ExternalResource:这是一种资源使用模式,它会提前建立好资源并且会在测试结束后将其销毁。这对于那些使用socket、嵌入式服务器等资源的测试来说很有用。
- ErrorCollector:可以让测试在失败后继续运行并在测试结束时报告所有错误。这对于那些需要验证大量独立条件的测试来说很有用(尽管这本身可能是个“test smell”)。
- ExpectedException:可以在测试中指定期望的异常类型与消息。
- Timeout:为类中的所有测试应用相同的超时时间。
例如,TimeOut这个Rule的使用。
import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; public class RuleTestDemo { //使用Timeout这个Rule @Rule public Timeout timeout = new Timeout(1000); @Test public void testMethod1() throws Exception { Thread.sleep(1001); } @Test public void testMethod2() throws Exception { Thread.sleep(999); } }
使用JUnit所提供的Timeout类,该类用于控制测试用例的执行超时时间。这里设置为1秒,当用例执行超过1秒则失败。接下来分别在 testMethod1和testMethod2两个用例中使用sleep()方法来控制用例的执行时间,显然testMethod1超过1秒,则运行失败。
自定义的Rule
除了可以使用JUnit框架自带的Rule,还可以根据自己的需求自定义Rule。简单来说,自定义一个Rule就是implement一个TestRule 接口,并实现apply()方法。该方法需要返回一个Statement对象。例子如下:
import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public class MethodNameRule implements TestRule { public Statement apply(final Statement base, final Description description) { return new Statement() { @Override public void evaluate() throws Throwable { //在测试方法运行之前做一些事情,在base.evaluate()之前 String className = description.getClassName(); String methodName = description.getMethodName(); base.evaluate(); //运行测试方法 //在测试方法运行之后做一些事情,在base.evaluate()之后 System.out.println("Class name:"+className+", method name: "+methodName); } }; } }
这里实现的功能是在每次测试用例运行之后,打印当前测试用例的类名和方法名。 在上面的例子中添加这里定义的MethodNameRule 。
…… public class RuleTestDemo { //使用Timeout这个Rule @Rule public Timeout timeout = new Timeout(1000); //使用自定义Rule, @Rule public MethodNameRule methodNameRule = new MethodNameRule(); ……
再次运行测试用例,执行结果如下: