一 mockito的使用
1.1 mockito介绍
Mockito是一个用于Java单元测试的mock框架,用于创建模拟对象(mock object)来替代真实对象,帮助开发者隔离外部依赖,从而专注于单元测试的逻辑,Mockito通常配合单元测试框架(如JUnit)使用。
1.2 坐标的引入
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.11.0</version>
<scope>test</scope>
</dependency>
二 验证行为
2.1 验证行为
使用verify()
检查mock对象的特定方法是否被调用,参数和调用次数是否符合预期。
Mockito 的 verify()
用于验证模拟对象的方法是否按预期被调用,包括调用次数、参数匹配等。它支持精确验证(如 times(2)
)、最少/最多次数(atLeast()
/atMost()
)、未调用(never()
)及顺序验证(结合 InOrder
)等,确保代码执行逻辑正确。
2.2 案例
2.2.1 案例代码
package com.ljf.services;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
import static org.mockito.Mockito.*;
/**
* @ClassName: MockTest
* @Description: TODO
* @Author: admin
* @Date: 2025/08/17 17:19:09
* @Version: V1.0
**/
@RunWith(MockitoJUnitRunner.class)
public class MockTest {
@Mock
List<String> strList;
@Test
public void test(){
strList.add("bj");
strList.add("sh");
strList.add("sz");
// 模拟调用
// 1. 验证方法被调用【恰好一次】(默认行为)
verify(strList).add("bj");
strList.add("bj");
// 2. 验证方法被调用【指定次数】
verify(strList, times(2)).add("bj"); // 精确2次
// 3. 验证方法【从未调用】
verify(strList, never()).clear();
// 4. 验证【调用顺序】
InOrder inOrder = inOrder(strList);
inOrder.verify(strList).add("bj");
inOrder.verify(strList).add("sh");
inOrder.verify(strList).add("sz");
verifyNoMoreInteractions(strList);
}
}
2.2.2 说明
验证单次调用:verify(strList).add("bj");→ 检查 add("bj") 被调用 1 次。
验证精确次数:verify(strList, times(2)).add("bj");→ 检查 add("bj") 被调用 2 次。
验证禁止调用:verify(strList, never()).clear();→ 确保 clear() 方法从未调用。
验证调用顺序:
InOrder inOrder = inOrder(strList);
inOrder.verify(strList).add("bj");
inOrder.verify(strList).add("sh");
inOrder.verify(strList).add("sz");
三 打桩
3.1 打桩
打桩:可以模拟数据库、网络请求等复杂或不可控的操作。无论调用多少次,一旦被打桩,方法将返回指定的值。模拟对象(Mock)的方法调用预设返回值或行为,使得测试代码可以隔离外部依赖,并控制方法的输出或异常
3.2 api说明
默认情况下,对于所有返回值的方法,mock对象将返回适当的默认值。例如,对于int
或Integer
返回0,对于boolean
或Boolean
返回false
,对于集合类型返回空集合,对于其他对象类型(例如字符串)返回null
。
参数匹配器:使用 any()
、eq()
等灵活匹配参数,但需注意参数一致性(不能混用具体值和匹配器)。
覆盖规则:最后一次打桩会覆盖之前的定义(例如多次对 mock.get(0)
打桩,以最后一次为准)。
3.3 返回值与没有返回值
when(...).thenX()
适用于有返回值的方法。doX().when(mock).method()
适用于 void 方法。
3.4 案例
package com.ljf.services;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
/**
* @ClassName: DaZhuangTest
* @Description: TODO
* @Author: admin
* @Date: 2025/08/17 17:47:42
* @Version: V1.0
**/
@RunWith(MockitoJUnitRunner.class)
public class DaZhuangTest {
@Mock
List<String> strList;
@Test
public void test(){
// 1. 创建模拟对象
// 2. 基础打桩:返回固定值
when(strList.get(0)).thenReturn("bj");
assertEquals("bj", strList.get(0));
// 3. 抛出异常
when(strList.get(1)).thenThrow(new RuntimeException("索引错误"));
assertThrows(RuntimeException.class, () -> strList.get(1));
// 4. 多次调用不同返回值
when(strList.size())
.thenReturn(1)
.thenReturn(2);
assertEquals(1, strList.size());
assertEquals(2, strList.size());
// 5. 参数匹配器(如 anyInt())
when(strList.get(anyInt())).thenReturn("default");
assertEquals("default", strList.get(999));
// 6. Void 方法打桩(如抛出异常)
doThrow(new IllegalStateException("清空失败")).when(strList).clear();
assertThrows(IllegalStateException.class,strList::clear);
}
}
未完待续.....