抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文介绍了Spring的测试方法。

环境

Windows 10 企业版 LTSC 21H2
Java 1.8
Maven 3.6.3
Spring 5.3.31
JUnit 5

1 简单使用

添加依赖:

pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- Spring Context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.31</version>
</dependency>
<!-- Spring Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.31</version>
<scope>test</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>

创建实体类:

java
1
2
3
4
5
6
7
8
@Component
public class User {
@Value("1")
private Integer id;
@Value("张三")
private String name;
// ...
}

创建配置类:

java
1
2
3
4
@Configuration
@ComponentScan("com.example")
public class DemoConfig {
}

创建测试类:

java
1
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 user = context.getBean(User.class);
// 使用User对象
System.out.println(user);
}
}

2 常用注解

2.1 @ExtendWith

使用@ExtendWith注解可以注册指定的扩展类,扩展类可以在测试执行的不同阶段插入自定义行为,从而增强测试的功能。

在Spring中测试使用SpringExtension扩展类,执行依赖注入,处理事务管理。

通常与@ContextConfiguration注解一起使用:

java
1
2
3
4
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = DemoConfig.class)
public class DemoTest {
}

2.2 @ContextConfiguration

使用@ContextConfiguration注解可以指定测试使用的配置类和配置文件。

指定配置类:

java
1
2
3
4
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = DemoConfig.class)
public class DemoTest {
}

指定配置文件:

java
1
2
3
4
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class DemoTest {
}

2.3 @SpringJUnitConfig

使用@SpringJUnitConfig注解属于组合注解,可以代替@ExtendWith注解和@ContextConfiguration注解。

指定配置类:

java
1
2
3
@SpringJUnitConfig(classes = DemoConfig.class)
public class DemoTest {
}

指定配置文件:

java
1
2
3
@SpringJUnitConfig(locations = "classpath:spring.xml")
public class DemoTest {
}

2.4 @Test

使用@Test注解可以标记测试方法。

指定配置类,使用测试方法:

java
1
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 user = context.getBean(User.class);
// 使用User对象
System.out.println(user);
}
}

指定配置文件,使用测试方法:

java
1
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 user = context.getBean(User.class);
// 使用User对象
System.out.println(user);
}
}

2.5 @ActiveProfiles

使用@ActiveProfiles注解可以指定测试使用的隔离环境。

指定配置类,指定隔离环境:

java
1
2
3
4
@SpringJUnitConfig(classes = DemoConfig.class)
@ActiveProfiles("dev")
public class DemoTest {
}

指定配置文件,指定隔离环境:

java
1
2
3
4
@SpringJUnitConfig(locations = "classpath:spring.xml")
@ActiveProfiles("dev")
public class DemoTest {
}

2.6 @DisplayName

使用@DisplayName注解可以为测试方法指定自定义的显示名称。

指定显示名称:

java
1
2
3
4
5
@Test
@DisplayName("测试方法")
public void test() {
// 测试代码
}

3 断言

断言是测试方法中的核心部分,用来验证代码行为是否符合预期,如果不符合预期则标记失败。如果前面断言失败,后面的代码都不会执行。

断言方法都是org.junit.jupiter.api.Assertions类中的静态方法。

3.1 简单断言

常用方法:

java
1
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);
// 断言对象为null
assertNull(actual, message);
// 断言对象不为null
assertNotNull(actual, message);
// 断言条件为true
assertTrue(condition, message);
// 断言条件为false
assertFalse(condition, message);

示例:

java
1
2
3
4
@Test
public void test() {
assertEquals(4, 2 + 2, "不相等");
}

3.2 数组断言

常用方法:

java
1
2
// 断言两个数组相等
assertArrayEquals(expected, actual, message);

示例:

java
1
2
3
4
@Test
public void test() {
assertArrayEquals(new int[]{1, 2, 3}, new int[]{1, 2, 3}, "不相等");
}

3.3 异常断言

常用方法:

java
1
2
// 断言抛出指定异常
assertThrows(expectedException, actual, message);

示例:

java
1
2
3
4
5
6
@Test
public void test() {
assertThrows(ArithmeticException.class, () -> {
System.out.println(1 / 0);
}, "没有抛出异常");
}

3.4 超时断言

常用方法:

java
1
2
// 断言在指定时间内完成执行
assertTimeout(timeout, executable, message);

示例:

java
1
2
3
4
5
6
@Test
public void test() {
assertTimeout(Duration.ofMillis(100), () -> {
Thread.sleep(80);
}, "执行超时");
}

3.5 批量断言

将多个断言批量执行,即使前面的断言失败,后面的断言也会继续执行,最后统计所有错误。

常用方法:

java
1
2
// 批量断言
assertAll(heading, executables);

示例:

java
1
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
1
2
// 断言失败
fail(message);

示例:

java
1
2
3
4
@Test
public void test() {
fail("快速失败");
}

4 假设

假设用于在特定条件不满足时标记跳过,而不是标记失败。如果前面假设失败,后面的代码都不会执行。

假设方法都是org.junit.jupiter.api.Assumptions类中的静态方法。

常用方法:

java
1
2
3
4
5
6
// 假设条件为true
assumeTrue(assumption, message);
// 假设条件为false
assumeFalse(assumption, message);
// 假设条件为true,如果成功则执行executable
assumingThat(assumption, executable);

示例:

java
1
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 单参数

示例:

java
1
2
3
4
5
@ParameterizedTest
@ValueSource(strings = {"a", "b", "c"})
void test(String s) {
assertNotNull(s);
}

5.2 空参数

示例:

java
1
2
3
4
5
@ParameterizedTest
@NullSource
void test(String s) {
assertNull(s);
}

5.3 表格参数

示例:

java
1
2
3
4
5
@ParameterizedTest
@CsvSource({"a,b,c", "d,e,f"})
void test(String s) {
assertNotNull(s);
}

5.4 方法参数

示例:

java
1
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");
}

评论