一、概述
【还在用 JUnit4(手把手教你迁移到 JUnit5)】在本教程中,我们将学习如何从 JUnit 4 迁移到最新的 JUnit 5 版本,并介绍两个版本的库之间的差异。
有关使用 JUnit 5 的一般指南,请参阅我们的文章 此处。
二、JUnit 5 的优势
让我们从以前的版本 JUnit 4 开始,它有一些明显的限制:
- 单个 jar 库包含整个框架。我们需要导入整个库,即使我们只需要一个特定的功能。 在 JUnit 5 中,我们获得了更多的粒度,并且可以只导入必要的内容。
- 在 JUnit 4 中一次只有一个测试运行器可以执行测试(例如 SpringJUnit4ClassRunner 或 Parameterized )。 JUnit 5 允许多个跑步者同时工作。
- JUnit 4 从未超越 Java 7,错过了 Java 8 的许多特性。JUnit 5 充分利用了 Java 8 特性。
三、差异 JUnit 4 被划分为组成 JUnit 5 的模块:
- JUnit Platform -- 此模块涵盖了我们可能感兴趣的所有扩展框架:测试执行、发现和报告。
- JUnit Vintage -- 此模块允许向后兼容 JUnit 4 甚至 JUnit 3。
JUnit 5 对其注释进行了重要更改。 最重要的一点是我们不能再使用 @Test 注释来指定期望。
JUnit 4 中的 expected 参数:
@Test(expected = Exception.class)
public void shouldRaiseAnException() throws Exception {
// ...
}
现在我们可以使用方法assertThrows:
public void shouldRaiseAnException() throws Exception {
Assertions.assertThrows(Exception.class, () -> {
//...
});
}
JUnit 4 中的 timeout 属性:
@Test(timeout = 1)
public void shouldFailBecauseTimeout() throws InterruptedException {
Thread.sleep(10);
}
现在 JUnit 5 中的 assertTimeout 方法:
@Test
public void shouldFailBecauseTimeout() throws InterruptedException {
Assertions.assertTimeout(Duration.ofMillis(1), () -> Thread.sleep(10));
}
以下是在 JUnit 5 中的一些更新:
- @Before annotation is now @BeforeEach
- @After annotation is now @AfterEach
- @BeforeClass annotation is now @BeforeAll
- @AfterClass annotation is now @AfterAll
- @Ignore annotation is now @Disabled
我们还可以在 JUnit 5 的 lambda 中编写断言消息,以便跳过复杂的消息构造:
@Test
public void shouldFailBecauseTheNumbersAreNotEqual_lazyEvaluation() {
Assertions.assertTrue(
2 == 3,
() -> "Numbers " + 2 + " and " + 3 + " are not equal!");
}
此外,我们可以在 JUnit 5 中对断言进行分组:
@Test
public void shouldAssertAllTheGroup() {
List list = Arrays.asList(1, 2, 4);
Assertions.assertAll("List is not incremental",
() -> Assertions.assertEquals(list.get(0).intValue(), 1),
() -> Assertions.assertEquals(list.get(1).intValue(), 2),
() -> Assertions.assertEquals(list.get(2).intValue(), 3));
}
3.3。假设
新的 Assumptions 类现在位于 org.junit.jupiter.api.Assumptions 中。 JUnit 5 完全支持 JUnit 4 中现有的假设方法,并且还添加了一组新方法,允许我们仅在特定场景下运行一些断言:
@Test
public void whenEnvironmentIsWeb_thenUrlsShouldStartWithHttp() {
assumingThat("WEB".equals(System.getenv("ENV")),
() -> {
assertTrue("http".startsWith(address));
});
}
3.4。标记和过滤
在 JUnit 4 中,我们可以使用 @Category 注释对测试进行分组。在 JUnit 5 中,@Category 注释被 @Tag 注释替换:
@Tag("annotations")
@Tag("junit5")
public class AnnotationTestExampleTest {
/*...*/
}
我们可以使用 maven-surefire-plugin 包含/排除特定标签:
maven-surefire-plugin
junit5
3.5。运行测试的新注释
在 JUnit 4 中,我们使用 @RunWithannotation 将测试上下文与其他框架集成,或者更改测试用例中的整体执行流程。
在 JUnit 5 中,我们现在可以使用 @ExtendWith 注释来提供类似的功能。
例如,要使用 JUnit 4 中的 Spring 功能:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
{"/app-config.xml", "/test-data-access-config.xml"})
public class SpringExtensionTest {
/*...*/
}
在 JUnit 5 中,这是一个简单的扩展:
@ExtendWith(SpringExtension.class)
@ContextConfiguration(
{ "/app-config.xml", "/test-data-access-config.xml" })
public class SpringExtensionTest {
/*...*/
}
3.6。新的测试规则注释
在 JUnit 4 中,我们使用 @Rule 和 @ClassRule 注释向测试添加特殊功能。
在 JUnit 5 中,我们可以使用 @ExtendWith 注释重现相同的逻辑。
例如,假设我们在 JUnit 4 中有一个自定义规则,用于在测试之前和之后编写日志跟踪:
public class TraceUnitTestRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
// Before and after an evaluation tracing here
...
}
};
}
}
我们在一个测试套件中实现它:
@Rule
public TraceUnitTestRule traceRuleTests = new TraceUnitTestRule();
在 JUnit 5 中,我们可以用更直观的方式编写相同的代码:
public class TraceUnitExtension implements AfterEachCallback, BeforeEachCallback {@Override
public void beforeEach(TestExtensionContext context) throws Exception {
// ...
}@Override
public void afterEach(TestExtensionContext context) throws Exception {
// ...
}
}
使用 org.junit.jupiter.api.extension 包中提供的 JUnit 5 的 AfterEachCallback 和 BeforeEachCallback 接口,我们可以在测试套件中轻松实现此规则:
@ExtendWith(TraceUnitExtension.class)
public class RuleExampleTest {
@Test
public void whenTracingTests() {
/*...*/
}
}
3.7。 JUnit 5 Vintage
JUnit Vintage 通过在 JUnit 5 上下文中运行 JUnit 3 或 JUnit 4 测试来帮助迁移 JUnit 测试。
我们可以通过导入 JUnit Vintage Engine 来使用它:
org.junit.vintage
junit-vintage-engine
${junit5.vintage.version}
test
四、结论 JUnit 5 是对 JUnit 4 框架的模块化和现代版。在本文中,我们介绍了这两个版本之间的主要区别,并展示了如何从一个版本迁移到另一个版本。
本文的完整实现可以在 GitHub 中找到。
推荐阅读
- 面试题每日一练|spring事务的隔离级别有哪些()
- 只需 6 步,你就可以搭建一个云原生操作系统原型
- 性能透明提升 50%!SMC + ERDMA 云上超大规模高性能网络协议栈
- 服务器|登录会话模型实战
- 【面试高频题】难度 3/5,求 LCS 具体方案变形题
- python基础教程|Python模块(基本概念、2种导入方法(import与from...import)和使用)
- python|python运行速度太慢(那是你打开的方式不对)
- Reactor And Gev 详解 通俗易懂
- golang|golang泛型介绍