1、添加单元测试依赖
本文使用的springboot版本是2.7.18版本,并已集成Mockito 4.5.1版本。
java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、添加两个测试类
TestBeanA类:
java
@Service
public class TestBeanA {
@Autowired
private TestBeanB testBeanB;
public int sayHello(String s){
String hello = testBeanB.getHello(s);
System.out.println("A:" + hello);
return 1;
}
}
TestBeanB类:
java
@Service
public class TestBeanB {
public String getHello(String s){
System.out.println("B:" + s);
return "hello world";
}
}
3、单元测试类
java
@ExtendWith(MockitoExtension.class)
public class MockTest {
// 自动把testBeanB注入到testBeanA
@InjectMocks
TestBeanA testBeanA;
// 模拟对象,方法不会执行
@Mock
// 真实对象,方法会执行
// @Spy
TestBeanB testBeanB;
@Test
public void test() {
when(testBeanB.getHello("mock")).thenReturn("Mock Hello");
System.out.println(testBeanA.sayHello("mock"));
verify(testBeanB, times(1)).getHello(anyString());
verify(testBeanB, never()).getHello("moc");
}
}
4、执行结果
java
A:Mock Hello
1
5、主要注解说明
@ExtendWith (MockitoExtension.class)
作用是让 JUnit5 测试框架整合 Mockito,自动管理 Mock 对象、依赖注入、生命周期。
无需手动调用 Mockito.initMocks(this),测试类中标记的对象自动生成:
@Mock:生成模拟对象,所有方法默认返回空值 /null;@Spy:基于真实对象创建间谍,真实方法会执行;@InjectMocks:自动把上面的 Mock/Spy 注入到被测试类的成员变量(构造器 /setter/ 字段注入)。
示例:
java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
// 自动mock
@Mock
private UserMapper userMapper;
// 自动把userMapper注入UserService
@InjectMocks
private UserService userService;
@Test
void testGetUser() {
when(userMapper.selectById(1L)).thenReturn(new User());
User user = userService.getById(1L);
assertNotNull(user);
}
}
verify(mock对象)
verify(mock对象) 用于校验某个 Mock 对象的指定方法是否被调用、调用次数、调用参数。 单元测试中用来断言:业务代码逻辑确实执行了依赖的 DAO / 工具类方法,验证流程符合预期。
默认 verify(mock) = 校验该方法被调用至少 1 次。
java
// 1. 无次数:校验方法执行过一次及以上
verify(userMapper).selectById(1L);
// 2. 精确次数校验
verify(userMapper, times(1)).selectById(1L);
// 3. 从未调用
verify(userMapper, never()).deleteById(any());
// 4. 最少、最多调用
verify(userMapper, atLeast(2)).listAll();
verify(userMapper, atMost(3)).listAll();
Mockito 参数匹配器:eq ()、any ()、anyString ()
when () 打桩、verify () 校验时,用来匹配方法入参,分为精准匹配、模糊匹配两类; 所有匹配器不能混用普通字面量,要么全匹配器,要么全常量。
eq(值):精准等值匹配,混合 any 时必用;any(Class):匹配任意该类型非 null 对象;anyString()/anyLong:基础类型专用模糊匹配;- 只要用了任意模糊匹配器,全部参数都要用匹配器包裹。
示例:
java
// 精准匹配参数必须等于 1L
when(mapper.selectById(eq(1L))).thenReturn(user);
verify(mapper).selectById(eq(1L));
等价写法(简单参数可省略 eq):
java
when(mapper.selectById(1L)).thenReturn(user);