Java单元测试工具JUnit 5新特性一览

MatildaIMNS 8年前

来自: http://blog.csdn.net/chszs/article/details/50662639

Java单元测试工具JUnit 5新特性一览

JUnit是最流行的开源Java单元测试工具,目前它的稳定版是4.12版。JUnit 4是2005年推出的,它基于Java 5的注释、反射等特性开发,距今已经超过十年了,受目前Java 8以及Lambda表达式等的影响,JUnit团队决定推出JUnit 5版。

目前JUnit 5已经推出了5.0.0 Alpha版,见: https://t.co/Mb12F3WF4A

一、JUnit 5的更新情况

JUnit 5完全使用当前的Java 8重写了所有代码,因此JUnit 5的运行条件是Java 8环境。

JUnit 5允许在断言中使用Lambda表达式,这个特性可以从开源的断言库AssertJ中可以看到。

AssertJ库见: http://joel-costigliola.github.io/assertj/

与JUnit 4不同,JUnit 5不再是单个库,而是模块化结构的集合,整个API分成了:自己的模块、引擎、launcher、针对Gradle和Surefire的集成模块。

JUnit团队还发起了名为Open Test Alliance for the JVM的活动,见: https://github.com/ota4j-team/opentest4j

JUnit 5的测试看上去与JUnit 4相同:同样是创建类,添加测试方法,使用@Test注释。但是,JUnit 5还提供了全新的一套注释集合,而且断言方法从JUnit 4的org.junit.Assert包移到了JUnit 5的org.junit.gen5.api.Assertions包。比如:

import org.junit.gen5.api.Assertions;  import org.junit.gen5.api.Test;  public class Test1 {    @Test    public void test()  {      Assertions.assertEquals(3 * 6, 18);      Assertions.assertTrue(5 > 4);    }  }

二、JUnit 5断言

JUnit 5的断言方法与JUnit 4相似,断言类提供了assertTrue、assertEquals、assertNull、assertSame以及相反的断言方法。不同之处在于JUnit 5的断言方法支持Lambda表达式。而且还有一个名为分组断言(Grouped Assertions)的新特性。

分组断言允许执行一组断言,且会一起报告。要记得在JUnit 4中,我们被告诫不要在一个测试中放入多个断言,以避免某些断言没有得到执行。现在,在JUnit 5中使用分组断言就无需再顾虑这个避讳了。

对JUnit 4的另一个改进是断言预期的异常。不再是以前那种把预期的异常类型放入@Test注释,或者是用try-catch包裹代码,JUnit 5使用assertThrows和equalsThrows断言。下面看看断言的例子:

public class Test2 {    @Test    public void lambdaExpressions() {      // lambda expression for condition      assertTrue(() -> "".isEmpty(), "string should be empty");      // lambda expression for assertion message      assertEquals("foo", "foo", () -> "message is lazily evaluated");    }    @Test    public void groupedAssertions() {      Dimension dim = new Dimension(800, 600);      assertAll("dimension",           () -> assertTrue(dim.getWidth() == 800, "width"),          () -> assertTrue(dim.getHeight() == 600, "height"));    }    @Test    public void exceptions() {      // assert exception type      assertThrows(RuntimeException.class, () -> {        throw new NullPointerException();      });      // assert on the expected exception      Throwable exception = expectThrows(RuntimeException.class, () -> {        throw new NullPointerException("should not be null");      });      assertEquals("should not be null", exception.getMessage());    }  }

三、假设、标签和禁止测试

假设、标签和禁止测试是JUnit 4的特性,在JUnit 5中仍然得以保留。不同的是假设中也支持Lambda表达式,假设的思想是如果假设条件没有得到满足,那么跳过测试执行。标签Tags等同于JUnit 4的测试分类的概念,可以对测试类和方法进行分类。JUnit 4禁止测试使用了@Ignore注释,而在JUnit 5中则使用@Disabled注释。

public class Test3 {    @Test    @Disabled    public void disabledTest() {          // ...      }    @Test    @Tag("jenkins")    public void jenkinsOnly() {      // ...    }      @Test    public void windowsOnly() {      Assumptions.assumeTrue(System.getenv("OS").startsWith("Windows"));      // ...    }  }

四、扩展模型

JUnit 5提供了一套新的扩展API,取代了以前的@RunWith和@Rule扩展机制。JUnit 4的测试类被限制到仅有一个Runner上,而新的扩展模型则允许一个类或方法keyii注册到多种扩展。

@ExtendWith(MockitoExtension.class)  @ExtendWith(CdiUnitExtension.class)  public class Test4 {    @Test    @DisplayName("awesome test")    void dependencyInjection(TestInfo testInfo) {      assertEquals("awesome test", testInfo.getDisplayName());    }  }

JUnit 5内建的扩展还支持方法级的依赖注入。

支持Hamcrest匹配和AssertJ断言库

JUnit 5支持Hamcrest匹配和AssertJ断言库,可以用它们来代替JUnit 5的方法。

public class Test5 {    @Test    public void emptyString() {      // JUnit 5      org.junit.gen5.api.Assertions.assertTrue("".isEmpty());        // AssertJ      org.assertj.core.api.Assertions.assertThat("").isEmpty();        // Hamcrest      org.hamcrest.MatcherAssert.assertThat("", isEmptyString());    }  }

JUnit 5的主页见: https://github.com/junit-team/junit5

有兴趣的朋友可以关注。

</div>