摘要:本文介绍了Spring的测试方法。
环境
Windows 10 企业版 LTSC 21H2
Java 1.8
Maven 3.6.3
Spring 5.3.31
JUnit 5
1 简单使用
添加依赖:
pom.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.31</version> </dependency>
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.31</version> <scope>test</scope> </dependency>
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency>
|
创建实体类:
java1 2 3 4 5 6 7 8
| @Component public class User { @Value("1") private Integer id; @Value("张三") private String name; }
|
创建配置类:
java1 2 3 4
| @Configuration @ComponentScan("com.example") public class DemoConfig { }
|
创建测试类:
java1 2 3 4 5 6 7 8 9 10 11 12 13
| @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = DemoConfig.class) public class DemoTest { @Resource private ApplicationContext context; @Test public void test() { User user = context.getBean(User.class); System.out.println(user); } }
|
2 常用注解
2.1 @ExtendWith
使用@ExtendWith注解可以注册指定的扩展类,扩展类可以在测试执行的不同阶段插入自定义行为,从而增强测试的功能。
在Spring中测试使用SpringExtension扩展类,执行依赖注入,处理事务管理。
通常与@ContextConfiguration注解一起使用:
java1 2 3 4
| @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = DemoConfig.class) public class DemoTest { }
|
2.2 @ContextConfiguration
使用@ContextConfiguration注解可以指定测试使用的配置类和配置文件。
指定配置类:
java1 2 3 4
| @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = DemoConfig.class) public class DemoTest { }
|
指定配置文件:
java1 2 3 4
| @ExtendWith(SpringExtension.class) @ContextConfiguration(locations = "classpath:spring.xml") public class DemoTest { }
|
2.3 @SpringJUnitConfig
使用@SpringJUnitConfig注解属于组合注解,可以代替@ExtendWith注解和@ContextConfiguration注解。
指定配置类:
java1 2 3
| @SpringJUnitConfig(classes = DemoConfig.class) public class DemoTest { }
|
指定配置文件:
java1 2 3
| @SpringJUnitConfig(locations = "classpath:spring.xml") public class DemoTest { }
|
2.4 @Test
使用@Test注解可以标记测试方法。
指定配置类,使用测试方法:
java1 2 3 4 5 6 7 8 9 10 11 12
| @SpringJUnitConfig(classes = DemoConfig.class) public class DemoTest { @Resource private ApplicationContext context; @Test public void test() { User user = context.getBean(User.class); System.out.println(user); } }
|
指定配置文件,使用测试方法:
java1 2 3 4 5 6 7 8 9 10 11 12
| @SpringJUnitConfig(locations = "classpath:spring.xml") public class DemoTest { @Resource private ApplicationContext context; @Test public void test() { User user = context.getBean(User.class); System.out.println(user); } }
|
2.5 @ActiveProfiles
使用@ActiveProfiles注解可以指定测试使用的隔离环境。
指定配置类,指定隔离环境:
java1 2 3 4
| @SpringJUnitConfig(classes = DemoConfig.class) @ActiveProfiles("dev") public class DemoTest { }
|
指定配置文件,指定隔离环境:
java1 2 3 4
| @SpringJUnitConfig(locations = "classpath:spring.xml") @ActiveProfiles("dev") public class DemoTest { }
|
2.6 @DisplayName
使用@DisplayName注解可以为测试方法指定自定义的显示名称。
指定显示名称:
java1 2 3 4 5
| @Test @DisplayName("测试方法") public void test() { }
|
3 断言
断言是测试方法中的核心部分,用来验证代码行为是否符合预期,如果不符合预期则标记失败。如果前面断言失败,后面的代码都不会执行。
断言方法都是org.junit.jupiter.api.Assertions类中的静态方法。
3.1 简单断言
常用方法:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| assertEquals(expected, actual, message);
assertNotEquals(unexpected, actual, message);
assertSame(expected, actual, message);
assertNotSame(unexpected, actual, message);
assertNull(actual, message);
assertNotNull(actual, message);
assertTrue(condition, message);
assertFalse(condition, message);
|
示例:
java1 2 3 4
| @Test public void test() { assertEquals(4, 2 + 2, "不相等"); }
|
3.2 数组断言
常用方法:
java1 2
| assertArrayEquals(expected, actual, message);
|
示例:
java1 2 3 4
| @Test public void test() { assertArrayEquals(new int[]{1, 2, 3}, new int[]{1, 2, 3}, "不相等"); }
|
3.3 异常断言
常用方法:
java1 2
| assertThrows(expectedException, actual, message);
|
示例:
java1 2 3 4 5 6
| @Test public void test() { assertThrows(ArithmeticException.class, () -> { System.out.println(1 / 0); }, "没有抛出异常"); }
|
3.4 超时断言
常用方法:
java1 2
| assertTimeout(timeout, executable, message);
|
示例:
java1 2 3 4 5 6
| @Test public void test() { assertTimeout(Duration.ofMillis(100), () -> { Thread.sleep(80); }, "执行超时"); }
|
3.5 批量断言
将多个断言批量执行,即使前面的断言失败,后面的断言也会继续执行,最后统计所有错误。
常用方法:
java1 2
| assertAll(heading, executables);
|
示例:
java1 2 3 4 5 6 7
| @Test public void test() { assertAll("批量断言", () -> assertEquals(4, 2 + 2, "不相等"), () -> assertArrayEquals(new int[]{1, 2, 3}, new int[]{1, 2, 3}, "不相等") ); }
|
3.6 快速失败
强制让当前单元测试立刻失败。
常用方法:
java
示例:
java1 2 3 4
| @Test public void test() { fail("快速失败"); }
|
4 假设
假设用于在特定条件不满足时标记跳过,而不是标记失败。如果前面假设失败,后面的代码都不会执行。
假设方法都是org.junit.jupiter.api.Assumptions类中的静态方法。
常用方法:
java1 2 3 4 5 6
| assumeTrue(assumption, message);
assumeFalse(assumption, message);
assumingThat(assumption, executable);
|
示例:
java1 2 3 4 5
| @Test public void test() { assumeTrue("OS" == "Windows", "不是Windows系统则跳过"); System.out.println("执行Windows系统特殊操作"); }
|
5 参数化测试
需要使用@ParameterizedTest注解,支持使用相同参数测试不同的方法,支持同时使用多个参数源。
常用参数源:
@ValueSource:支持传入相同类型的参数依次进行测试。
@EnumSource:支持传入枚举类型的参数进行测试。
@NullSource:支持传入null值进行测试。
@EmptySource:支持传入空值进行测试。
@CsvSource:支持传入CSV格式的参数进行测试。
@CsvFileSource:支持传入CSV文件中的参数进行测试。
@MethodSource:支持传入方法作为参数源进行测试。
5.1 单参数
示例:
java1 2 3 4 5
| @ParameterizedTest @ValueSource(strings = {"a", "b", "c"}) void test(String s) { assertNotNull(s); }
|
5.2 空参数
示例:
java1 2 3 4 5
| @ParameterizedTest @NullSource void test(String s) { assertNull(s); }
|
5.3 表格参数
示例:
java1 2 3 4 5
| @ParameterizedTest @CsvSource({"a,b,c", "d,e,f"}) void test(String s) { assertNotNull(s); }
|
5.4 方法参数
示例:
java1 2 3 4 5 6 7 8 9
| @ParameterizedTest @MethodSource("strings") void test(String s) { assertNotNull(s); }
static Stream<String> strings() { return Stream.of("a", "b", "c"); }
|
条