概念
单元测试,用于检查和验证 程序中的各个单元(通常是函数、方法或类 )是否按照预期工作(是否符合预期)。
库
库 | 解释 |
---|---|
JUnit | 单元测试框架,提供了一组注解和断言来编写和运行测试 |
Spring Test和SpringBootTest | 提供了一些方便的工具和注解来进行集成测试和组件测试。 |
AssertJ | 断言库,提供了丰富的断言来编写清晰、易读的测试代码。 |
Hamcrest | 匹配器库,用于编写灵活和可读的断言。 |
Mockito | 用于创建和管理模拟对象,帮助模拟外部依赖、行为和状态。 |
注解
@SpringBootTest
:用于加载Spring应用程序上下文。@AutoConfigureMockMvc
:用于自动配置MockMvc实例。@Transactional
:开启事务功能。@Rollback()
:事务回滚,默认true。@ParameterizedTest
:用于支持参数化测试 。@CsvSource
、@ValueSource
、@MethodSource
@Mock
:创建模拟对象。@MockBean
:创建模拟对象,会注入到 Spring 上下文。@Spy
:创建真实 对象,并可以部分模拟该对象的行为。@InjectMocks
:标记一个待测对象(被测试类的对象),用于注入被测试类 中的依赖(注入模拟对象)。
Assertions
类
在JUnit
测试中,Assertions
类提供了一系列用于验证测试结果的静态方法。
-
assertEquals(expected, actual)
:验证两个值是否相等。适用于比较基本数据类型、对象或数组等。javaassertEquals(5, result); // 比较整数值 assertEquals("expected", result); // 比较字符串值 assertEquals(expectedObject, actualObject); // 比较对象 assertEquals(expectedArray, actualArray); // 比较数组
-
assertTrue(condition)
:验证给定的条件是否为真。 -
assertFalse(condition)
:验证给定的条件是否为假。 -
assertNull(object)
:验证给定对象是否为空。 -
assertNotNull(object)
:验证给定对象是否不为空。 -
assertSame(expected, actual)
:验证两个对象引用是否指向同一个对象。 -
assertNotSame(unexpected, actual)
:验证两个对象引用是否指向不同的对象。 -
assertThrows(expectedType, executable)
:验证代码块是否抛出了指定类型的异常。
单元测试步骤
| 💡 Navigate → Test :自动生成测试类。
注意 :Controller
层的单元测试,可以使用 MockMvc
模拟HTTP请求。
- 准备测试数据:在测试方法之前,准备好必要的测试数据,包括输入参数、模拟的依赖对象等。
- 模拟依赖对象 :使用
Mockito
等框架模拟Controller
、Service
层依赖的其他对象,例如Repository
、外部服务等。- 若不使用模拟对象 ,直接
@Autowired
注入测试即可。
- 若不使用模拟对象 ,直接
- 调用被测试的方法 :在测试方法中调用
Controller
、Service
层的方法,传入准备好的测试数据。 - 验证行为:使用断言 验证方法的行为和返回结果是否符合预期
Mock
在面向对象程序中,模拟对象 (mock object)是以可控方式模拟真实对象行为 的假对象。
在编程过程中,通常通过模拟一些输入数据,来验证程序是否达到预期结果。
如果在单元测试中无法使用真实对象,可采用模拟对象进行替代。
MockMvc:模拟HTTP请求
MockMvc
Spring提供的用于模拟HTTP请求 的工具,它允许模拟请求 并验证控制器的行为和响应。
在单元测试和集成测试中,MockMvc
可以用来测试控制器的端到端行为,而不需要启动整个应用程序服务器。
MockMvc构造
三种方法
mockMvc = MockMvcBuilders.standaloneSetup(new Testontroller()).build();
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
@AutoConfigureMockMvc
注解用于自动配置MockMvc
实例。
MockMvc使用
mockMvc
.perform
执行一个请求,返回值ResultActions
。MockMvcRequestBuilders
.get
("/xx/xx")构造一个get
请求。MockMvcRequestBuilders
类提供的各种静态方法构建不同类型的请求,如GET
、POST
、PUT
、DELETE
等。contentType
设置发送的数据格式accept
设置返回的数据格式param
添加请求传值header
设置请求头
ResultActions
.andExpect
添加执行完成后的断言 。- 使用断言 是判断结果是否符合期望。
- 使用
MockMvcResultMatchers
类提供的各种静态方法构建断言,例如status()
、content()
、header()
等。 - 使用
MockMvcResultMatchers.status().isOk()
来断言预期的HTTP状态码是否为200(OK)。
ResultActions
.andDo
添加一个结果处理器 ,表示要对结果做点什么事情。比如处使用print()
输出整个响应结果信息。ResultActions
.andReturn
表示执行完成后返回相应的结果。
@Mock
@Mock
是 Mockito 框架中的注解,用于创建模拟对象。@Mock
只能用于普通的单元测试(例如,不涉及 Spring 应用程序上下文的测试),通常与MockitoJUnitRunner
或MockitoAnnotations.initMocks()
配合使用。- 它创建的模拟对象是纯粹的模拟对象,不会受到 Spring 上下文的影响,因此不会自动注入到 Spring 容器中。
@MockBean
@MockBean
是 Spring Boot Test 模块中的注解,用于创建模拟对象 ,并将其注入到 Spring 上下文 中,以便在集成测试中使用。@MockBean
可以用于测试 Spring 上下文中的组件,例如服务、存储库、控制器等。- 它创建的模拟对象是由 Spring 管理的 Bean,可以被自动注入到其他 Spring Bean 中。
@Mock
和 @MockBean
区别(是否注入)
@Mock
用于创建纯粹的模拟对象@MockBean
用于在 Spring 上下文 中创建模拟对象,并将其注入到其他 Spring Bean 中,以便在集成测试中使用。
@Spy
@Spy
是 Mockito 框架中的一个注解,用于创建一个真实对象 ,并部分模拟该对象的行为。
与 @Mock
注解不同,@Spy
注解创建的对象是真实对象 ,但可以选择性地模拟部分方法的行为。
@InjectMocks
和 @Mock
@InjectMocks
:标记一个待测对象(被测试类的对象),用于注入被测试类 中的依赖。
@Mock
用于创建模拟对象 ,@InjectMocks
用于将这些 模拟对象 注入 到被测试对象中,以便进行单元测试。
@ParameterizedTest
注解
用于支持参数化测试 。为测试方法 提供一组不同的参数 ,以便多次 运行相同的测试逻辑 ,但使用不同的输入参数。
@CsvSource
用于提供一组参数 给参数化测试方法 。使用逗号分隔的字符串表示多个参数,每个字符串代表一个测试案例。
java
@ParameterizedTest
@CsvSource({"1, 1, 2", "2, 3, 5", "5, 5, 10"})
void testAddition(int a, int b, int expectedSum) {
int actualSum = a + b;
assertEquals(expectedSum, actualSum, "Sum of " + a + " and " + b + " should be " + expectedSum);
}
@ParameterizedTest
注解表示该方法是一个参数化测试方法。@CsvSource
注解提供了一组参数,每一行代表一个测试案例。- 在这个示例中,提供了三组参数,每组参数包含两个整数和一个预期的结果。
- 参数化测试方法
testAddition()
接受三个参数:两个整数和一个预期的结果。- 测试方法将对这些参数执行加法操作,并使用断言验证实际的结果是否与预期的结果相匹配。
@ValueSource
用于提供基本类型 或字符串类型 的参数 。逗号分隔多个参数,每个参数代表一个测试案例。
java
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testIsPositive(int number) {
//验证参数是否为正数
assertTrue(number > 0);
}
@MethodSource
用于指定一个方法 来提供参数给参数化测试方法。
@MethodSource
注解,可以将参数提供逻辑 从测试类中抽取到一个单独的方法中,以提高代码的可读性和可维护性。
java
@ParameterizedTest
@MethodSource("stringProvider")
void testStringLength(String input, int expectedLength) {
assertEquals(expectedLength, input.length());
}
// 参数提供逻辑 抽取到 一个单独的方法
static Stream<Arguments> stringProvider() {
return Stream.of(
Arguments.of("apple", 5),
Arguments.of("banana", 6),
Arguments.of("orange", 6)
);
}