junit5文档介绍

JUnit5引入了新的注解如@BeforeEach、@AfterEach,支持动态测试、嵌套测试和条件测试。它还允许测试非public方法,提供了更灵活的测试执行顺序和更强的扩展机制。此外,JUnit5对断言和假设进行了改进,并支持类和方法级别的标记过滤。

junit4和junit5区别

特性JUnit4JUnit5
声明一个测试方法@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. 自带的不好用

第三方库

AssertJHamcrestTruth

假设

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 {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值