单元测试笔记
分类:
笔记
标签:
junit5
mockito
创建时间:2024-05-31 16:45:39.0
修改时间:2024-05-31 16:45:39.0
前言
最近写很多单元测试 一直没记录
今天整理一下 常见的demo 方便后续速查
https://junit.org/junit5/docs/current/user-guide/#overview
JUnit5注解汇总
基础测试控制
注解 | 含义 | 使用场景 |
@Test | 标记测试方法 | 单个测试逻辑的验证 |
@BeforeEach | 每个测试方法前执行 | 初始化测试环境 |
@AfterEach | 每个测试方法后执行 | 清理测试环境 |
@BeforeAll | 整个测试类执行前运行 | 初始化全局资源 |
@AfterAll | 整个测试类执行后运行 | 清理全局资源 |
@Disabled | 禁用测试方法 | 暂时跳过测试 |
@Tag | 标记测试,支持按标签执行 | 组织和筛选测试 |
@DisplayName | 设置显示名称 | 提高测试输出可读性 |
参数化测试
注解 | 含义 | 使用场景 |
@ParameterizedTest | 参数化的测试 | 验证不同输入值的行为 |
@ValueSource | 提供固定值作为参数 | 参数列表 |
@EnumSource | 提供枚举值作为参数 | 枚举遍历 |
@CsvSource / @CsvFileSource | CSV数据作为参数 | 数据驱动测试 |
测试控制和异常测试
注解 | 含义 | 使用场景 |
@RepeatedTest | 重复执行测试 | 验证稳定性 |
@AssertThrows | 验证方法抛出预期异常 | 异常处理测试 |
扩展和定制
注解 | 含义 | 使用场景 |
@TestExtension | 定义测试扩展 | 自定义测试行为 |
@RegisterExtension | 注册测试扩展 | 使用自定义扩展 |
@TempDir | 提供临时目录 | 存储临时文件 |
@Import | 引入额外配置类 | 测试上下文扩展 |
mockito
注解 | 作用 | 使用场景 |
@Mock | 创建一个模拟对象,可以控制其行为和返回值。 | 当需要隔离测试,不依赖真实对象时。 |
@Spy | 创建一个真实对象的代理,可以部分模拟,其他行为保持不变。 | 当需要测试部分真实行为,同时控制某些方法时。 |
@InjectMocks | 自动注入依赖,通常用于创建被测试对象,其中依赖项由@Mock 或@Spy 注解的实例填充。 | 当测试类需要依赖模拟对象时。 |
@Captor | 配合ArgumentCaptor 使用,捕获方法调用的参数。 | 当需要验证方法调用的参数时。 |
@RunWith(MockitoJUnitRunner.class) | 使用Mockito运行器,初始化@Mock 和@Spy 注解的实例。 | 在JUnit测试类中使用,代替@Before 初始化模拟对象。 |
@Before | 初始化方法,通常用于配置模拟对象。 | 需要在每个测试方法之前执行的初始化逻辑。 |
@After | 清理方法,通常用于清理模拟对象。 | 需要在每个测试方法之后执行的清理逻辑。 |
@MockBean | Spring Boot测试中创建模拟的Spring Bean。 | 当测试需要模拟Spring容器中的Bean时。 |
@SpyBean | Spring Boot测试中创建真实Bean的代理,可以部分模拟。 | 当测试需要部分模拟Spring容器中的Bean时。 |
@WithMockUser | Spring Security测试中模拟登录用户的身份。 | 当测试需要模拟不同用户权限时。 |
@MockitoSettings | 控制Mockito框架的全局设置,如严格性、默认答案等。 | 当需要自定义Mockito的行为时。 |
@ExtendWith(MockitoExtension.class) | JUnit 5中初始化Mockito,替代@RunWith(MockitoJUnitRunner.class) 。 | 在JUnit 5测试类中使用。 |
Mockito 主要类和函数
Mockito 类与函数
类名 | 函数 | 描述 |
Mockito | mock(Class<T> classToMock) | 创建模拟对象,不执行实际操作。 |
| when(T toMock) | 定义模拟对象的行为,设置方法调用的返回值或行为。 |
| thenReturn(T value) | 模拟方法调用时返回指定值。 |
| thenThrow(Throwables... toThrow) | 模拟方法调用时抛出异常。 |
| doAnswer(Answer answer) | 自定义方法调用的处理逻辑。 |
| doNothing() | 方法调用不执行任何操作,不返回值。 |
| doCallRealMethod() | 使模拟方法调用实际实现。 |
| verify(T mock) | 验证模拟对象的方法是否被调用。 |
| verifyNoMoreInteractions(Object... mocks) | 验证没有其他未验证的交互。 |
| verifyZeroInteractions(Object... mocks) | 验证模拟对象未被调用。 |
ArgumentMatchers 辅助类
函数 | 描述 |
any() | 匹配任何参数值。 |
anyVararg() | 匹配任何变长参数。 |
eq(T value) | 匹配与给定值相等的参数。 |
Assertions 主要方法
JUnit Jupiter (org.junit.jupiter.api.Assertions
)
方法 | 描述 |
assertEquals(expected, actual) | 验证预期值与实际值相等。 |
assertNotEquals(expected, actual) | 验证预期值与实际值不相等。 |
assertTrue(condition) | 验证条件为真。 |
assertFalse(condition) | 验证条件为假。 |
assertNull(object) | 验证对象为 null。 |
assertNotNull(object) | 验证对象非 null。 |
assertSame(expected, actual) | 验证预期对象与实际对象是同一个对象。 |
assertNotSame(expected, actual) | 验证预期对象与实际对象不是同一个对象。 |
assertAll(Executable... executables) | 批量执行多个断言。 |
示例
- 基本依赖 starter包包含了 junit5和mockito
testImplementation "org.springframework.boot:spring-boot-starter-test"
package com.ming;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
public class DemoTest {
@BeforeEach
public void init() {
System.out.println("init");
}
@AfterEach
public void destroy() {
System.out.println("destroy");
}
@Test
public void test() {
System.out.println("test");
}
}
mock静态方法 以前是用powermock junit5之后 mockito也提供mock的方式
// https://mvnrepository.com/artifact/org.mockito/mockito-inline
testImplementation group: 'org.mockito', name: 'mockito-inline', version: '5.2.0'
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@ExtendWith(SpringExtension.class)
public class MockStaticTest {
private MockedStatic<StaticTestService> mockStatic;
@BeforeEach
public void setUp() {
mockStatic = org.mockito.Mockito.mockStatic(StaticTestService.class);
}
@AfterEach
public void tearDown() {
mockStatic.close();
}
@Test
public void testNoArg() {
mockStatic.when(StaticTestService::testNoArg).thenReturn("test");
assertEquals("test", StaticTestService.testNoArg());
}
@Test
public void testArg() {
mockStatic.when(() -> StaticTestService.testArg("arg")).thenReturn("test");
assertEquals("test", StaticTestService.testArg("arg"));
assertNotEquals("test", StaticTestService.testArg("arg1"));
}
}
class StaticTestService {
public static String testNoArg() {
return "????";
}
public static String testArg(String str) {
return "????";
}
}
ReflectionTestUtils.setField(testService, “字段名”, “字段赋值”);
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.util.ReflectionTestUtils;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ExtendWith(SpringExtension.class)
public class MockTest {
@InjectMocks
private TestService testService;
@Test
public void test() {
assertEquals("????ming-default", testService.getStr());
ReflectionTestUtils.setField(testService, "str", "ming-update");
assertEquals("????ming-update", testService.getStr());
}
}
class TestService {
private String str = "ming-default";
public String getStr() {
return "????" + str;
}
}
如果用到lambdaXXXXX 需要注入 TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), “”), xxxxEntity.class);
总结
就是常见的单元测试方法
junit5 已经成为一个java的单元测试平台了
常见的操作 基本覆盖
配合mockito基本够用