JUnit的Rule的使用

 2023-09-15 阅读 24 评论 0

摘要:我们在使用JUnit的时候,为了使测试结果更加清晰明确,会有以下的需求: 一个类有多个测试方法,想知道日志是哪个测试方法想在所有测试方法的前后加上一些语句,用于初始化和销毁一些资源如果一个测试方法可能抛出多个异常,想知道运行时

我们在使用JUnit的时候,为了使测试结果更加清晰明确,会有以下的需求:

  • 一个类有多个测试方法,想知道日志是哪个测试方法

  • 想在所有测试方法的前后加上一些语句,用于初始化和销毁一些资源

  • 如果一个测试方法可能抛出多个异常,想知道运行时到底抛出哪些异常

  • java handler机制的原理?...

以上的需求可以通过为每个方法加上相似的语句来实现,但这样未免有点麻烦和冗余,好在JUnit4为我们提供了一劳永逸的方法,使用Rule。

Rule简介

Rule是JUnit4.7加入的新特性,有点类似于拦截器,用于在测试方法执行前后添加额外的处理。实际上是@Before,@After的另一种实现。使用时需要放在实现了TestRule的成员变量上或者返回TestRule的方法上,且修饰符为public。Rule会应用于该类每个测试方法。

内置Rule

JUnit提供了很多内置的TestRule的实现满足日常使用,具体有如下:

  • Verifier:所有测试结束后对测试执行结果添加额外的逻辑验证测试最终成功与否。该抽象类为子类提供一个接口方法verify()供扩展

        String result = "success";/*** Verifier:用于在测试方法执行结束后,进行一些结果校验*/@Rulepublic Verifier verifier = new Verifier() {@Overrideprotected void verify() throws Throwable {if (result.equals("fail")) {throw new Exception("failed");}}};@Testpublic void verifierTest() {result = "fail";}

    junit怎么用。运行结果:

    java.lang.Exception: failed
    ...
  • ErrorCollector:是Verifier类的一个子类实现,用于在测试执行过程中收集错误信息,不会中断测试,最后调用verify()方法处理。

        /*** ErrorCollector:可以收集多个多个异常,并在方法结束后一起打印出来*/@Rulepublic ErrorCollector errorCollector = new ErrorCollector();@Testpublic void errorCollectorTest() {errorCollector.addError(new RuntimeException("error 1"));System.out.println("==================================");errorCollector.addError(new RuntimeException("error 2"));}

    运行结果:

    ==================================
    java.lang.RuntimeException: error 1
    ...
    java.lang.RuntimeException: error 2
    ...
  • TemporaryFolder:是抽象类ExternalResource的一个子类实现,用于在JUnit测试执行前后,创建和删除临时目录

        /*** TemporaryFolder:创建临时目录/文件,测试方法执行结束后自动删除* 可以在构造方法中传入使用的父目录,否则默认使用系统临时目录*/@Rulepublic TemporaryFolder temporaryFolder = new TemporaryFolder(new File("C:\\Users\\test"));@Testpublic void temporaryFolderTest() throws IOException, InterruptedException {temporaryFolder.newFolder("test");temporaryFolder.newFile("hello.txt");Thread.sleep(10 * 1000);}
  • TestName:是抽象类TestWatcher的一个子类实现,用于在测试执行过程中获取测试方法名称。在starting()中记录测试方法名,在getMethodName()中返回

    /*** TestName:获取当前测试方法的方法名*/@Rulepublic TestName testName = new TestName();@Testpublic void testNameTest() {System.out.println("method is " + testName.getMethodName());}

    junit常用注解。运行结果:

      method is testNameTest
  • TestWatcher:监视测试方法生命周期的各个阶段。该抽象类为子类提供了五个接口方法succeeded(), failed(), skipped(), starting()及finished()供扩展

        /*** TestWatcher:在测试方法开始,结束,成功,失败,跳过这些时间点调用相应方法*/@Rulepublic TestWatcher testWatcher = new TestWatcher() {@Overrideprotected void succeeded(Description description) {System.out.println("success");}@Overrideprotected void failed(Throwable e, Description description) {System.out.println("failed");}@Overrideprotected void starting(Description description) {System.out.println("starting");}@Overrideprotected void finished(Description description) {System.out.println("finished");}@Overrideprotected void skipped(AssumptionViolatedException e, Description description) {System.out.println("skipped");}};@Testpublic void testWatcherTest() {System.out.println("testWatcher");}

    运行结果:

    starting
    testWatcher
    success
    finished
  • Timeout:与@Test中的timeout相对应,@Test只能修饰待测试方法,Timeout可以修饰待测试类

    /*** Timeout:超时时间,方法运行超时则抛出TestTimedOutException异常*/@Rulepublic Timeout timeout = new Timeout(5, TimeUnit.SECONDS);@Testpublic void timeoutTest() throws InterruptedException {System.out.println("timeout");Thread.sleep(6*1000);}

    运行结果:

      org.junit.runners.model.TestTimedOutException: test timed out after 5 seconds...
  • ExpectedException:与@Test中的expected相对应,提供更强大灵活的异常验证功能,@Test只能修饰待测试方法,ExpectedException可以修饰待测试类

        /*** ExpectedException:指定测试方法出现的异常,未出现或者出现其他类型的异常测试不通过*/@Rulepublic ExpectedException expectedException=ExpectedException.none();@Testpublic void expectedExceptionTest(){expectedException.expect(NullPointerException.class);throw new RuntimeException();}

    运行结果:

    java.lang.AssertionError: 
    Expected: an instance of java.lang.NullPointerExceptionbut:  is a java.lang.RuntimeException

自定义Rule

当内置的Rule无法满足你的需求的时候,你还可以通过实现TestRule来自定义Rule。

  • 自定义RuleTest实现类

    /*** 自己实现TestRule*/
    public class MyTestRule implements TestRule {/*** @param base 基础行为,要进行封装的行为* @param description test方法的描述,包括方法名,类名等* @return 可以使在基础行为上添加新动作,也可以是一个全新的动作*/@Overridepublic Statement apply(Statement base, Description description) {return new Statement() {@Overridepublic void evaluate() throws Throwable {String name = description.getMethodName();System.out.println("开始调用" + name);base.evaluate();System.out.println("结束调用" + name);}};}
    }

    使用自定义的Rlue类:

      @Rulepublic MyTestRule myTestRule=new MyTestRule();@Testpublic void myTestRuleTest(){System.out.println("myTestRuleTest");}

    运行结果:

    开始调用myTestRuleTest
    myTestRuleTest
    结束调用myTestRuleTest
  • 使用匿名类自定义Rule

        @Rulepublic TestRule myRule(){TestRule rule = (base, description) -> new Statement() {@Overridepublic void evaluate() throws Throwable {String name = description.getMethodName();System.out.println("start invoke " + name);base.evaluate();System.out.println("finished invoke " + name);}};return rule;}@Testpublic void myRuleTest(){System.out.println("myRule");}

    运行结果:

    start invoke myRuleTest
    myRule
    finished invoke myRuleTest

转载于:https://www.cnblogs.com/henryyao/p/10789484.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/63134.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息