如何做网站搜索栏,企业网网页,北京规划网站,html 教程单元测试是软件开发过程中的一种验证手段#xff0c;它针对最小的可测试部分#xff08;通常是函数或方法#xff09;进行检查和验证。其实单元测试还是挺重要的#xff0c;不过国内很多公司的项目其实并没有做好单元测试#xff0c;或者根本就没做单元测试#xff0c;原… 单元测试是软件开发过程中的一种验证手段它针对最小的可测试部分通常是函数或方法进行检查和验证。其实单元测试还是挺重要的不过国内很多公司的项目其实并没有做好单元测试或者根本就没做单元测试原因可能是项目周期比较紧张开发时间不充足所以就省略了单元测试也有可能是领导不重视单元测试。之前工作中做单元测试主要用到JUnit和TestNG,做覆盖统计主要用的JaCoCo。不过本篇主要总结JUnit5的知识点及用法。JUnit5官网JUnit 5
目录
1.Junit5简介和环境搭建
2.JUnit 5 的主要注解 3.JUnit 5 断言Assertions 4.JUnit 5 测试方法
5. JUnit 5 测试执行控制
6.JUnit 5 测试输出 7.JUnit 5 测试辅助功能
8.JUnit 5 错误处理和异常测试
9.JUnit 5 测试依赖注入
10.JUnit 5 测试监听器
11.JUnit 5 测试配置
12. JUnit 5 测试动态生成
13.JUnit 5 测试参数化
14.JUnit 5 测试并行执行
15.JUnit 5 测试可读性
16.JUnit 5 测试条件
17.Spring Boot项目集成Junit5 1.Junit5简介和环境搭建
特性描述JUnit 5 架构JUnit 5 由三个主要模块组成JUnit Platform、JUnit Jupiter 和 JUnit Vintage。JUnit Platform提供了一个测试框架的运行时平台允许IDE和构建工具在JVM上启动和请求测试。JUnit Jupiter提供了新的编程模型和扩展模型用于编写测试。JUnit Vintage允许JUnit 5运行JUnit 3和JUnit 4的测试。环境搭建使用Maven或Gradle将JUnit 5添加到项目中。
环境搭建 使用Maven或Gradle将JUnit 5添加到项目中。
dependency
groupIdorg.junit.jupiter/groupId
artifactIdjunit-jupiter-api/artifactIdversion5.7.0/versionscopetest/scope/dependency
2.JUnit 5 的主要注解
注解描述代码示例BeforeEach在每个测试方法执行之前运行的方法。 BeforeEach
public void init() {
... } AfterEach在每个测试方法执行之后运行的方法。AfterEach public void tearDown() { ... } BeforeAll在所有测试方法执行之前整个类中只运行一次。 BeforeAll public static void setUpBeforeClass() { ... } AfterAll在所有测试方法执行之后整个类中只运行一次。 AfterAll public static void tearDownAfterClass() { ... } Test标记一个方法为测试方法。 Test public void myTestMethod() { ... } RepeatedTest允许测试方法重复执行指定次数。 RepeatedTest(10) public void repeatedTestMethod() { ... } ParameterizedTest用于参数化测试。 ParameterizedTest public void parameterizedTestMethod(int param) { ... } MethodSource与ParameterizedTest一起使用提供测试参数。 MethodSource(parameters)
public void parameterizedTestMethod(int param) {
...
} static StreamObject[] parameters() {
return Stream.of(new Object[]{1}); } 3.JUnit 5 断言Assertions
断言方法描述代码示例assertAll()允许组合多个断言如果任何一个断言失败测试会立即失败。 assertAll(Test Group, () - assertEquals(2, 1 1), () - assertEquals(foo, bar)); assertNotNull()验证对象不是null。 assertNotNull(Object should not be null, myObject); assertNull()验证对象是null。 assertNull(Object should be null, myObject); assertTrue()验证条件为true。 assertTrue(Should be true, condition); assertFalse()验证条件为false。 assertFalse(Should be false, condition); assertEquals()验证两个值是否相等。 assertEquals(2, 1 1); assertNotEquals()验证两个值是否不相等。 assertNotEquals(Should not be equal, 2, 3); assertSame()验证两个引用是否指向同一个对象。 Object obj1 new Object(); Object obj2 obj1; assertSame(obj1, obj2); assertNotSame()验证两个引用是否指向不同的对象。 assertNotSame(Should not be same, obj1, obj2);
以上是JUnit 5中常用的断言方法它们帮助开发者验证测试用例中的预期结果是否符合实际结果。 4.JUnit 5 测试方法
特性描述代码示例测试方法使用Test注解标记的方法JUnit 5将自动运行这些方法作为测试。 Test public void testMethod() { ... } 测试方法参数测试方法可以接收参数如测试数据。 ParameterizedTest public void testMethod(String data) { ... } 超时测试使用Timeout注解设置测试方法的最大执行时间。 Test Timeout(value 500, unit TimeUnit.MILLISECONDS) public void testMethod() { ... } 动态测试使用DynamicTest注解创建动态生成的测试。 TestFactoryStreamDynamicTest dynamicTestsStream() {
return Stream.of(Test1, Test2) .map(data - DynamicTest.dynamicTest(data, () - {...
}
));
} 条件测试使用EnabledIf或DisabledIf注解根据条件启用或禁用测试。 EnabledIf(expression) Test public void testMethod() { ... }
5. JUnit 5 测试执行控制
控制方式描述代码示例标签Tags使用Tag注解给测试分类可以通过标签过滤运行特定测试。 Tag(fast) Test public void fastTestMethod() { ... } 测试配置Test Configuration使用TestInstance注解控制测试方法的生命周期。 TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MyTestClass { ... } 测试筛选器Test Filters使用JUnit 5的内置筛选器来选择要运行的测试。在命令行中使用 -include 或 --exclude 选项。测试依赖Test Dependencies使用ExtendWith注解定义测试类或方法的依赖关系。 ExtendWith(CustomExtension.class) public class MyTestClass { ... } 重复测试Repeated Tests使用RepeatedTest注解让测试方法重复执行。 RepeatedTest(5) public void repeatedTestMethod() { ... } 参数化测试Parameterized Tests使用ParameterizedTest和MethodSource注解执行参数化测试。 ParameterizedTest MethodSource(dataProvider) public void parameterizedTest(int param) { ... } static Stream? dataProvider() { return Stream.of(1, 2, 3); } 临时文件夹Temporary Folders使用TempDir注解为测试方法提供临时文件夹路径。 Test public void testWithTempFolder(TempDir Path tempDir) { ... }
以上是JUnit 5中测试执行控制的一些关键特性它们允许开发者更灵活地控制测试的执行流程和条件。
6.JUnit 5 测试输出
特性描述代码示例断言消息使用断言方法的重载版本提供自定义的失败消息。 assertEquals(List should contain B, A, list.get(1)); 日志记录使用LogMessageRule注解捕获日志消息。 Rule public LogMessageRule rule new LogMessageRule(); Test public void testLogCapture() { rule.expect(WARNING); logger.warn(This is a warning message); } 测试输出Test Output使用TestInfo获取测试信息如测试方法名称、显示名称等。 Test public void testWithTestInfo(TestInfo testInfo) { System.out.println(Running test: testInfo.getDisplayName()); } 测试模板方法Test Template Methods使用TestTemplate注解定义模板方法结合ExtendWith注解使用。 TestTemplate public void testTemplateMethod(MyCustomExtension ext) { ... } ExtendWith(MyCustomExtension.class) public void extendWithMethod() { ... } 动态测试Dynamic Tests生成动态测试用例返回Stream的DynamicTest。 TestFactory StreamDynamicTest dynamicTests() { return Stream.of(A, B, C) .map(input - DynamicTest.dynamicTest(input, () - assertEquals(1, input.length()))); } 7.JUnit 5 测试辅助功能
功能描述代码示例假设Assumptions使用假设来避免在不满足特定条件时执行测试。assumeTrue(This test assumes JDK 11 or higher, javaVersion 11); 测试时钟Test Clock使用MockClock注解模拟时间用于时间相关的测试。 Test MockClock(12:00:00) public void testWithMockClock() { ... } 测试资源Test Resources使用RegisterExtension注解注册测试资源如临时文件、数据库连接等。 RegisterExtension public TemporaryFolder folder new TemporaryFolder(); Test public void testWithTemporaryFolder() { Path path folder.getRoot().toPath(); ... } 测试规则Test Rules使用测试规则来为测试方法提供额外的行为如日志捕获、重复测试等。 Rule public TestRule logWatcher new LogWatcher(); Test public void testWithLogWatcher() { ... } 条件测试Conditional Tests根据系统属性或环境变量的条件执行测试。 EnabledIfEnvironment(os.name Windows 10) Test public void windows10OnlyTest() { ... } 测试配置参数Test Configuration Parameters从命令行或配置文件中读取参数并在测试中使用。 Test public void testWithConfigurationParameter(ConfiguredParameter(timeout) int timeout) { ... } 测试模板方法Test Template Methods允许为测试提供自定义的执行逻辑。 TestTemplate public void testTemplateMethod(MyCustomExtension ext) { ... } ExtendWith(MyCustomExtension.class) public void extendWithMethod() { ... }
这些辅助功能增强了JUnit 5的测试能力使得测试更加灵活和强大
8.JUnit 5 错误处理和异常测试
特性描述代码示例期望异常Expected Exceptions使用assertThrows来验证方法是否抛出了特定的异常。 Assertions.assertThrows(IllegalArgumentException.class, () - { throw new IllegalArgumentException(bad argument); }); 异常测试Exception Testing使用Test注解的expectedExceptions属性来测试预期的异常。 Test(expectedExceptions ArithmeticException.class) public void testDivideByZero() { int i 1 / 0; } 断言异常内容Asserting Exception Content捕获异常并验证其内容如消息或原因。 Exception exception assertThrows(IllegalArgumentException.class, () - { throw new IllegalArgumentException(error); }); assertEquals(error, exception.getMessage()); 错误收集Error Collecting使用assertAll来执行多个断言即使其中一个失败其他断言也会继续执行。 assertAll(test, () - assertEquals(2, 1 1), () - assertThrows(RuntimeException.class, () - { throw new RuntimeException(); })); 软断言Soft Assertions使用软断言来收集多个失败的断言而不是在第一个失败时立即停止测试。 SoftAssertions softly new SoftAssertions(); softly.assertThat(codePointBefore(a)).isEqualTo(-1); softly.assertThat(codePointBefore(A)).isEqualTo(-1); softly.assertAll(); 这些特性帮助开发者更好地处理测试中的异常情况确保测试的准确性和健壮性。
9.JUnit 5 测试依赖注入
特性描述代码示例构造器注入使用Autowired注解在测试类构造器中注入依赖。 SpringBootTest public class MySpringBootTest { Autowired private MyService service; } 字段注入使用Inject注解在字段上注入依赖。 public class MyTestClass { Inject private MyService service; } 方法参数注入使用InjectMocks注解在测试方法的参数上注入依赖。Test public void testMethod(Mocked MyDependency dependency) { ... } 模块化测试使用ExtendWith注解和自定义扩展来模块化测试逻辑。 ExtendWith(MyExtension.class) public class MyTestClass { ... } 测试实例化使用TestInstance注解控制测试类的实例化方式。 TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MyTestClass { ... } 测试上下文管理使用TestInfo获取测试上下文信息如测试方法名称、测试类等。public class MyTestClass { Test public void testMethod(TestInfo testInfo) { System.out.println(testInfo.getDisplayName()); } }
依赖注入是现代测试框架中的重要特性它允许测试代码更加模块化和可重用。JUnit 5通过集成Spring等框架提供了强大的依赖注入支持。
10.JUnit 5 测试监听器
特性描述代码示例监听器Listeners使用ExtendWith注解添加监听器监听测试的生命周期事件。 ExtendWith(MyTestWatcher.class) public class MyTestClass { ... } 测试执行监听器Test Execution Listeners实现TestExecutionListener接口监听测试的执行过程。 public class MyTestExecutionListener implements TestExecutionListener { ... } 测试实例监听器Test Instance Listeners实现TestInstanceListener接口监听测试实例的创建和生命周期。public class MyTestInstanceListener implements TestInstanceListener { ... } 测试生命周期监听器Test Lifecycle Listeners实现TestLifecycleListener接口监听测试的整个生命周期。 public class MyTestLifecycleListener implements TestLifecycleListener { ... } 测试失败监听器Test Failure Listeners实现TestFailureListener接口监听测试失败事件。 public class MyTestFailureListener implements TestFailureListener { ... } 测试告警监听器Test Alerting Listeners实现TestAlerting接口对测试失败进行告警。 public class MyTestAlerting implements TestAlerting { ... }
测试监听器是JUnit 5中用于监听和响应测试事件的强大机制它们可以用来扩展JUnit 5的功能如测试报告生成、性能监控等。
11.JUnit 5 测试配置
配置项描述使用示例全局配置通过junit-platform.properties文件进行全局配置。junit.jupiter.conditions.include-classes-with-at-least-one-method true测试方法配置使用注解在测试方法上指定配置。 Test DisplayName(A test with custom display name) void testMethod() { ... } 测试类配置使用注解在测试类上指定配置。 TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MyTestClass { ... } 测试模板配置使用注解在测试模板方法上指定配置。 TestTemplate public void testTemplate() { ... } 参数化测试配置使用注解在参数化测试方法上指定配置。 ParameterizedTest(name {index} {0} {1} {2}) MethodSource(dataProvider) void parameterizedTest(int a, int b, int expected) { ... } 测试过滤器配置使用注解或命令行参数来过滤测试。在命令行中使用 --filter 选项。测试重复配置使用注解在测试方法上指定重复次数。 RepeatedTest(3) void repeatedTestMethod() { ... } 测试超时配置使用注解在测试方法上指定执行超时时间。Test Timeout(duration 500, unit TimeUnit.MILLISECONDS) void testMethod() { ... }
测试配置是JUnit 5中用于定制测试行为的重要特性它允许开发者根据需要调整测试的执行方式。
12. JUnit 5 测试动态生成
特性描述代码示例动态测试Dynamic Tests允许在测试执行期间动态生成测试用例。TestFactory StreamDynamicTest dynamicTests() { return Stream.of(foo, bar) .map(s - DynamicTest.dynamicTest(s, () - assertNotEquals(0, s.length()))); } 测试工厂Test Factories创建动态测试的方法可以返回Stream或Iterable的DynamicTest。 TestFactory StreamDynamicTest dynamicTestsWithStream() { return Stream.of(1, 2, 3) .map(i - DynamicTest.dynamicTest(Test with i, () - {})); } 测试模板方法Test Template Methods使用模板方法来定义测试逻辑并通过扩展执行不同的测试用例。 TestTemplate void testWithCustomProvider(Object o) { ... } ExtendWith(CustomProviderExtension.class) void extendWithCustomProvider() { ... } 测试扩展Test Extensions自定义扩展可以介入测试执行的各个阶段实现自定义逻辑。 public class CustomExtension implements TestExecutionListener { ... }
动态生成测试用例是JUnit 5中一个强大的特性它允许开发者根据需要灵活地生成测试用例从而提高测试的复用性和灵活性。
13.JUnit 5 测试参数化
特性描述代码示例参数化测试Parameterized Tests允许为单个测试方法提供多个输入参数。 ParameterizedTest MethodSource(numbersProvider) void parameterizedTest(int number) { ... } static StreamInteger numbersProvider() { return Stream.of(1, 2, 3); } 方法源Method Source提供测试参数的来源可以是静态方法或字段。 static StreamArguments numbersProvider() { return Stream.of(Arguments.of(1), Arguments.of(2), Arguments.of(3)); } CSV源CSV Source使用CSV格式的字符串直接提供测试参数。 ParameterizedTest CsvSource({ 1, 2, 3, 4, 5, 6 }) void parameterizedTest(int a, int b, int c) { ... } 对象数组源Object Array Source使用对象数组直接提供测试参数。 ParameterizedTest ArgumentsSource(ObjectArraySource.class) void parameterizedTest(String data) { ... } 自定义提供器Custom Providers创建自定义的参数提供器来生成测试参数。 public class CustomProvider implements ArgumentsProvider { public Stream? extends Arguments provideArguments(ExtensionContext context) { return Stream.of(Arguments.of(A, B)); } }
参数化测试是JUnit 5中用于测试多种输入组合的强大特性它允许开发者编写更简洁、更高效的测试代码。
14.JUnit 5 测试并行执行
特性描述代码示例并行执行Parallel Execution允许同时运行多个测试以加快测试套件的执行速度。使用JUnit 5的junit.jupiter.execution.parallel.enabled配置属性来启用并行执行。测试类级别的并行对整个测试类中的测试方法进行并行执行。 TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MyTestClass { ... } 方法级别的并行对单个测试方法进行并行执行。使用JUnit 5的junit.jupiter.execution.parallel.mode.default配置属性来设置默认的并行模式。自定义并行策略通过实现TestExecutionListener接口来自定义测试的并行执行策略。 public class CustomParallelismListener implements TestExecutionListener { ... } 资源隔离确保在并行执行过程中测试之间的资源是隔离的避免相互干扰。使用RegisterExtension注解的ResourceLock规则来锁定特定资源。动态测试并行对动态生成的测试用例进行并行执行。在TestFactory方法中返回的DynamicTest流可以被并行执行。
测试并行执行是提高测试效率的重要特性它可以有效减少持续集成CI环境中的测试等待时间。
15.JUnit 5 测试可读性
特性描述代码示例显示名称Display Name为测试方法提供可读性强的显示名称。 DisplayName(Test with custom display name) Test public void testMethod() { ... } 嵌套测试Nested Tests使用嵌套的测试方法来组织测试逻辑提高测试的可读性。 Test public void outerTest() { Test public void innerTest() { ... } } 测试描述Test Description提供测试的描述信息增强测试的可读性。使用TestInfo获取测试的描述信息并在测试日志中展示。断言消息Assertion Messages在断言失败时提供自定义的消息帮助理解失败的原因。 assertEquals(Expected reference equality, obj1, obj2); 测试模板Test Templates使用测试模板方法来提供可读性强的测试逻辑。 TestTemplate void testWithCustomProvider(Object o) { ... }
测试可读性是JUnit 5中用于提高测试代码和测试报告可读性的重要特性它有助于开发者更好地理解和维护测试代码。
16.JUnit 5 测试条件
特性描述代码示例条件注解Conditional Annotations根据条件启用或禁用测试如系统属性、环境变量等。 EnabledIf(javaVersion 11) Test public void testMethod() { ... } 系统属性条件System Property Condition根据系统属性的值来启用或禁用测试。 EnabledIfSystemProperty(named os.arch, matches .*64.*) Test public void testMethod() { ... } 环境变量条件Environment Variable Condition根据环境变量的值来启用或禁用测试。 EnabledIfEnvironmentVariable(named CI, matches true) Test public void testMethod() { ... } 自定义条件Custom Conditions实现Condition接口来提供自定义的条件逻辑。 public class CustomCondition implements Condition { ... } 测试配置参数Test Configuration Parameters从命令行或配置文件中读取参数并在测试中使用。 Test public void testWithConfigurationParameter(ConfiguredParameter(timeout) int timeout) { ... }
测试条件是JUnit 5中用于根据环境或配置来控制测试执行的重要特性它允许开发者灵活地决定哪些测试应该运行。
17.Spring Boot项目集成Junit5 17.1首先确保你的pom.xmlMaven或build.gradleGradle文件中包含了JUnit 5和Spring Boot Test的依赖。
对于Mavenpom.xml可能包含以下依赖
dependencies!-- Spring Boot Test Starter --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdversion2.5.0/version !-- 使用你项目匹配的版本 --scopetest/scope/dependency
/dependencies 对于Gradlebuild.gradle可能包含以下依赖
dependencies {// Spring Boot Test StartertestImplementation(org.springframework.boot:spring-boot-starter-test:2.5.0) // 使用你项目匹配的版本
}
17.2 创建测试类
创建一个测试类使用SpringBootTest注解来指示Spring Boot为测试提供支持。使用Test注解标记测试方法。
这里是一个简单的服务层测试示例
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;SpringBootTest
public class SomeServiceTest {Autowiredprivate SomeService someService;MockBeanprivate SomeDependency someDependency;Testpublic void testSomeMethod() {// 设置mock行为when(someDependency.someMethod()).thenReturn(expected value);// 调用待测试的方法String result someService.someMethod();// 验证结果assertEquals(expected value, result);// 验证依赖是否被调用verify(someDependency).someMethod();}
} 这个例子中SomeService是我们想要测试的服务层组件而SomeDependency是它的一个依赖项我们使用MockBean注解来创建一个模拟对象。
17.3 运行测试
你可以在IDE中运行测试或者使用Maven或Gradle的命令行工具来执行测试。
对于Maven使用以下命令 mvn test 对于Gradle使用以下命令 ./gradlew test 这只是一个极简单的示例在项目的具体需求下测试会更复杂包括更多的模拟对象服务和测试用例等。