doReturn().when()` 与 `when().thenReturn()` 的区别

Mockito 提供两种方式配置方法的返回值:doReturn().when()when().thenReturn()。虽然它们功能相似,但行为差异显著,需根据具体场景选择使用。


1. 语法对比
方法语法示例
when().thenReturn()when(mock.method()).thenReturn(value)
doReturn().when()doReturn(value).when(mock).method()

2. 核心区别
特性when().thenReturn()doReturn().when()
是否执行真实方法执行真实方法(对 Spy 对象而言)不执行真实方法(直接覆盖行为)
适用方法类型非 void 方法任意方法(包括 void 方法)
异常处理若真实方法抛异常,需先处理安全跳过真实方法执行,避免异常
链式调用支持 .thenReturn().thenThrow()需通过 doReturn().doThrow().when() 链式调用

3. 典型场景分析
场景 1:对 Spy 对象配置桩(避免执行真实方法)

问题:使用 when().thenReturn() 时,Spy 对象的真实方法会被执行。
示例

List<String> realList = new ArrayList<>();
List<String> spyList = spy(realList);

// 错误:add("A") 会被实际执行,导致列表包含 "A"
when(spyList.add("A")).thenReturn(true);  

// 正确:add("A") 不会执行
doReturn(true).when(spyList).add("A");
场景 2:Mock void 方法

问题when() 无法直接用于 void 方法。
示例

// 错误:语法不合法,因为 mockLogger.error() 是 void 方法
when(mockLogger.error(anyString())).thenReturn(...);  

// 正确:使用 doNothing() 或 doReturn()
doNothing().when(mockLogger).error(anyString());
doReturn(true).when(mockLogger).error(anyString()); // 假设修改返回类型
场景 3:绕过异常方法

问题:真实方法可能抛出异常(如未初始化)。
示例

public class Service {
    public String getConfig() {
        throw new RuntimeException("未初始化!");
    }
}

Service spyService = spy(new Service());

// 错误:调用 getConfig() 抛出异常
when(spyService.getConfig()).thenReturn("default");  

// 正确:跳过真实方法
doReturn("default").when(spyService).getConfig();

4. 链式调用对比
when().thenReturn() 链式调用
when(mockList.get(0))
    .thenReturn("A")  // 第一次调用返回 "A"
    .thenReturn("B"); // 后续调用返回 "B"
doReturn().when() 链式调用
doReturn("A")
    .doReturn("B")
    .when(mockList).get(0);

5. 最佳实践
场景推荐方法理由
普通 Mock 对象(非 Spy)when().thenReturn()语法简洁,直观易读
Spy 对象或需跳过真实方法执行doReturn().when()避免副作用(如状态修改、异常抛出)
Void 方法配置doNothing().when()唯一合法选择
多次调用不同返回值均可,根据对象类型选择when() 更简洁,但需注意是否需执行真实方法

6. 总结
  • when().thenReturn():默认选择,适用于普通 Mock 对象的非 void 方法。
  • doReturn().when()
    • 处理 Spy 对象,避免执行真实方法。
    • 配置 void 方法 的返回值。
    • 绕过可能抛出异常的真实方法调用

正确选择方法可避免意外的副作用,提升测试的稳定性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值