junit4和junit5区别
| 特性 | JUnit4 | JUnit5 |
|---|---|---|
| 声明一个测试方法 | @Test | @Test【长的一样但是包不一样】 |
| 在当前类的所有测试方法执行前要执行的方法 | @BeforeClass | @BeforeAll |
| 在当前类的所有测试方法执行后要执行的方法 | @AfterClass | @AfterAll |
| 每个测试方法执行前要执行的方法 | @Before | @BeforeEach |
| 每个测试方法执行后要执行的方法 | @After | @AfterEach |
| 忽略某个测试方法或测试类 | @Ignore | @Disabled |
| 动态测试用例生成工厂 | 无此特性 | @TestFactory |
| 嵌套测试 | 无此特性 | @Nested |
| 标记与过滤 | @Category | @Tag |
| 注册定制扩展点 | 无此特性 | @ExtendWith |
jdk版本要求不一样
断言Assertions
假定Assumptions
标记与过滤
测试用例簇(Test Suites)
JUnit5允许测试非public方法
第三方集成
具体请看 JUnit4和JUnit5的主要区别_junit4和junit5的区别_pilaf1990的博客-CSDN博客
注解
| 注解 | 描述 |
|---|---|
@Test | 表示方法是测试方法。与 JUnit 4 的@Test注释不同,此注释不声明任何属性,因为 JUnit Jupiter 中的测试扩展基于它们自己的专用注释进行操作。此类方法将被继承,除非它们被覆盖。 |
@ParameterizedTest | 表示方法是参数化测试。此类方法将被继承,除非它们被覆盖。 |
@RepeatedTest | 表示方法是重复测试的测试模板。此类方法将被继承,除非它们被覆盖。 |
@TestFactory | 表示方法是动态测试的测试工厂。此类方法将被继承,除非它们被覆盖。 |
@TestTemplate | 表示方法是测试用例的模板,设计用于根据注册提供者返回的调用上下文的数量多次调用。此类方法将被继承,除非它们被覆盖。 |
@TestClassOrder | 用于配置注解测试类中测试类的测试类执行顺序。@Nested这样的注解是继承的。 |
@TestMethodOrder | 用于配置注解测试类的测试方法执行顺序;类似于 JUnit 4 的@FixMethodOrder. 这样的注解是继承的。 |
@TestInstance | 用于为带注释的测试类配置测试实例生命周期。这样的注解是继承的。 |
@DisplayName | 声明测试类或测试方法的自定义显示名称。此类注释不会被继承。 |
@DisplayNameGeneration | 为测试类声明自定义显示名称生成器。这样的注解是继承的。 |
@BeforeEach | 表示被注解的方法应该在当前类中的每个, , , 或方法之前执行; 类似于 JUnit 4 的. 此类方法是继承的——除非它们被覆盖或取代(即,仅根据签名进行替换,而不考虑 Java 的可见性规则)。 @Test``@RepeatedTest``@ParameterizedTest``@TestFactory``@Before |
@AfterEach | 表示被注解的方法应该在当前类中的每个, , , 或方法之后执行; 类似于 JUnit 4 的. 此类方法是继承的——除非它们被覆盖或取代(即,仅根据签名进行替换,而不考虑 Java 的可见性规则)。 @Test``@RepeatedTest``@ParameterizedTest``@TestFactory``@After |
@BeforeAll | 表示被注解的方法应该在当前类中的所有, , , 和方法之前 执行;类似于 JUnit 4 的. 此类方法是继承的——除非它们被隐藏、覆盖或取代(即,仅基于签名替换,而不考虑 Java 的可见性规则)——并且必须是,除非使用“每类”测试实例生命周期。 @Test``@RepeatedTest``@ParameterizedTest``@TestFactory``@BeforeClass``static |
@AfterAll | 表示被注解的方法应该在当前类中的所有, , , 和方法之后 执行;类似于 JUnit 4 的. 此类方法是继承的——除非它们被隐藏、覆盖或取代(即,仅基于签名替换,而不考虑 Java 的可见性规则)——并且必须是,除非使用“每类”测试实例生命周期。 @Test``@RepeatedTest``@ParameterizedTest``@TestFactory``@AfterClass``static |
@Nested | 表示被注释的类是一个非静态的嵌套测试类。在 Java 8 到 Java 15 中,@BeforeAll除非使用“每类”测试实例生命周期@AfterAll,否则不能直接在测试类中使用方法。从 Java 16 开始,可以使用任一测试实例生命周期模式在测试类中声明方法。此类注释不会被继承。@Nested``@BeforeAll``@AfterAll``static``@Nested |
@Tag | 用于在类或方法级别声明过滤测试的标签;类似于 TestNG 中的测试组或 JUnit 4 中的类别。此类注释在类级别继承,但不在方法级别继承。 |
@Disabled | 用于禁用测试类或测试方法;类似于 JUnit 4 的@Ignore. 此类注释不会被继承。 |
@Timeout | 如果测试、测试工厂、测试模板或生命周期方法的执行超过给定持续时间,则用于使测试、测试工厂、测试模板或生命周期方法失败。这样的注解是继承的。 |
@ExtendWith | 用于以声明方式注册扩展。这样的注解是继承的。 |
@RegisterExtension | 用于通过字段以编程方式注册扩展。这些字段是继承的,除非它们被隐藏。 |
@TempDir | 用于在生命周期方法或测试方法中通过字段注入或参数注入提供临时目录;位于org.junit.jupiter.api.io包中。 |
定义
Container
测试树中包含其他容器或测试作为其子节点的节点(例如测试类)。
Test
测试树中的一个节点,用于验证执行时的预期行为(例如@Test方法)。
生命周期方法
任何直接用 @BeforeAll、@AfterAll、@BeforeEach或进行注释或元注释的方法@AfterEach。
测试类
任何顶级类、static成员类或@Nested类 至少包含一个测试方法的,即容器。测试类不能abstract而且必须有一个构造函数。
测试方法
@Test任何用, @RepeatedTest, @ParameterizedTest, @TestFactory, 或直接注解或元注解的实例方法 @TestTemplate。除了,它们在测试树中 @Test创建一个容器,用于对**测试进行分组,或者可能(对于@TestFactory),其他容器。
测试类和方法
测试类、测试方法和生命周期方法不需要是public,但它们不能是private
展示名称
@DisplayName("A special test case")
断言
org.junit.jupiter.api.Assertions class. 自带的不好用
第三方库
假设
assumeTrue("CI".equals(System.getenv("ENV"))); 如果报错,灰色,测试跳过,不是失败
//一些其他用法
assumingThat("CI".equals(System.getenv("ENV")),
() -> {
// perform these assertions only on the CI server 只在C1环境断言
assertEquals(2, calculator.calculate("4/2"));
});
禁用测试
@Disabled
类和方法上都可用
条件测试
在package org.junit.jupiter.api.condition包下
@Test @EnabledOnOs({ LINUX, MAC })
@Test @EnabledOnOs(value = MAC, architectures = "aarch64")
@EnabledOnJre({ JAVA_9, JAVA_10 })
@EnabledForJreRange(min = JAVA_9, max = JAVA_11)
自定义条件
@EnabledIf("customCondition") //双引号里是方法名称
@DisabledIf("customCondition")
@Test
@DisabledIf("customCondition")
void disabled() {
// ...
}
boolean customCondition() {
return true;
}
标记和过滤
@Tag("fast")
测试类和方法可以通过@Tag注解来标记。这些标记稍后可用于过滤测试发现和执行
测试执行顺序
方法顺序
-
MethodOrderer.DisplayName:根据显示名称按字母数字顺序对测试方法进行排序(请参阅显示名称生成优先规则) -
MethodOrderer.MethodName:根据名称和形式参数列表按字母数字顺序对测试方法进行排序 -
MethodOrderer.OrderAnnotation:根据通过注释指定的值对测试方法进行数字排序@Order -
MethodOrderer.Random:伪随机排序测试方法并支持自定义种子的配置 -
MethodOrderer.Alphanumeric:根据名称和形式参数列表按字母数字顺序对测试方法进行排序;已弃用MethodOrderer.MethodName,将在 6.0 中删除
@TestMethodOrder(OrderAnnotation.class)
方法 用 @Order(3) 来标记顺序
统一配置信息:新建一个配置文件,命名为 junit-platform.properties
src/test/resources/junit-platform.properties
方法顺序
junit.jupiter.testmethod.order.default = \ org.junit.jupiter.api.MethodOrderer$OrderAnnotation
类顺序
junit.jupiter.testclass.order.default = \ org.junit.jupiter.api.ClassOrderer$OrderAnnotation
类顺序
测试实例生命周期
@TestInstance(Lifecycle.PER_CLASS)每个类一个测试实例 @TestInstance(Lifecycle.PER_METHOD) 每个方法一个测试实例
配置信息
junit.jupiter.testinstance.lifecycle.default = per_class
嵌套测试
依赖注入
重复测试
@RepeatedTest(10)
重复10次
参数化测试
测试不同的场景,只写一个方法
@ParameterizedTest
@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" })
void palindromes(String candidate) {
assertTrue(StringUtils.isPalindrome(candidate));
}
测试模板
@TestTemplate
动态测试
@TestFactory
超时测试
@Timeout(5) @Timeout(value = 2, unit = TimeUnit.SECONDS) junit.jupiter.execution.timeout.mode 共有三种模式:enabled、disabled和disabled_on_debug
并行执行
junit.jupiter.execution.parallel.enabled=true junit.jupiter.execution.parallel.mode.default= SAME_THREAD 或者 CONCURRENT
内置拓展
@TempDir
拓展模型
@ExtendWith注解使用,有以下拓展接口可以实现
//Supported Extension APIs ExecutionCondition InvocationInterceptor TestInstanceFactory TestInstancePostProcessor 后置处理 ParameterResolver TestExecutionExceptionHandler 异常处理 LifecycleMethodExecutionExceptionHandler TestTemplateInvocationContextProvider BeforeAllCallback AfterAllCallback BeforeEachCallback AfterEachCallback BeforeTestExecutionCallback AfterTestExecutionCallback TestInstancePreDestroyCallback
例如@ExtendWith(MockitoExtension.class)
可以在单元测试类里直接用mock注解,因为MockitoExtension已经为我们初始化好了mock需要的东西
public class MockitoExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
@Override
public void beforeEach(final ExtensionContext context) {
List<Object> testInstances = context.getRequiredTestInstances().getAllInstances();
Strictness actualStrictness = this.retrieveAnnotationFromTestClasses(context)
.map(MockitoSettings::strictness)
.orElse(strictness);
MockitoSession session = Mockito.mockitoSession()
.initMocks(testInstances.toArray())
.strictness(actualStrictness)
.logger(new MockitoSessionLoggerAdapter(Plugins.getMockitoLogger()))
.startMocking();
context.getStore(MOCKITO).put(MOCKS, new HashSet<>());
context.getStore(MOCKITO).put(SESSION, session);
}
...
}
例如springExtension类的结构
public class SpringExtension implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor,
BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback,
ParameterResolver {
...
}
如果您使用的是 Junit 版本 < 5,则必须使用 @RunWith(SpringRunner.class) 或 @RunWith(MockitoJUnitRunner.class) 等。
如果您使用的是 Junit 版本 = 5,那么您必须使用 @ExtendWith(SpringExtension.class) 或 @ExtendWith(MockitoExtension.class) 等
@SpringbootTest 注解中已经有包含了 @ExtendWith({SpringExtension.class})
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith({SpringExtension.class})
public @interface SpringBootTest {
}
异常处理拓展
// 如下可以记录下来所有的错误
class RecordStateOnErrorExtension implements LifecycleMethodExecutionExceptionHandler {
@Override
public void handleBeforeAllMethodExecutionException(ExtensionContext context, Throwable ex)
throws Throwable {
memoryDumpForFurtherInvestigation("Failure recorded during class setup");
throw ex;
}
@Override
public void handleBeforeEachMethodExecutionException(ExtensionContext context, Throwable ex)
throws Throwable {
memoryDumpForFurtherInvestigation("Failure recorded during test setup");
throw ex;
}
@Override
public void handleAfterEachMethodExecutionException(ExtensionContext context, Throwable ex)
throws Throwable {
memoryDumpForFurtherInvestigation("Failure recorded during test cleanup");
throw ex;
}
@Override
public void handleAfterAllMethodExecutionException(ExtensionContext context, Throwable ex)
throws Throwable {
memoryDumpForFurtherInvestigation("Failure recorded during class cleanup");
throw ex;
}
}
其他自行查阅官网junit5
suite 打成一套执行
import org.junit.platform.suite.api.IncludeClassNamePatterns;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;
@Suite
@SuiteDisplayName("JUnit Platform Suite Demo")
@SelectPackages("example")
@IncludeClassNamePatterns(".*Tests")
class SuiteDemo {
}
JUnit5引入了新的注解如@BeforeEach、@AfterEach,支持动态测试、嵌套测试和条件测试。它还允许测试非public方法,提供了更灵活的测试执行顺序和更强的扩展机制。此外,JUnit5对断言和假设进行了改进,并支持类和方法级别的标记过滤。

1239

被折叠的 条评论
为什么被折叠?



