Mockito中thenReturn()与thenAnswer()的区别是什么?
Mockito中thenReturn()与thenAnswer()的核心差异及适用场景
核心差异
二者最本质的区别是返回值的计算时机、上下文获取能力不同:
- 执行时机不同
thenReturn()的参数值是在定义Mock规则阶段就提前计算完成的,不管后续该Mock方法被调用多少次,返回的都是预先生成的固定值。你示例中写的thenReturn(callMethod1(obj)),callMethod1会在写Stub代码的那一刻直接执行,后续Mock方法被调用时不会再重新运行callMethod1的逻辑。thenAnswer()的回调逻辑是每次Mock方法被实际调用时才会执行,每次调用都会重新运行一次回调内的代码,返回值可跟随调用上下文动态变化。
- 上下文获取能力不同
thenReturn()无法拿到当前调用Mock方法时传入的实际参数、调用信息,只能返回提前准备好的固定值。thenAnswer()可以通过回调参数(比如你示例中的val)获取本次调用的所有入参、方法元数据等信息,支持基于实际调用场景做逻辑处理。
- 性能开销不同
thenReturn()直接返回预计算的值,无额外执行开销,性能更好。thenAnswer()每次调用都要执行回调逻辑,开销相对更高。
适用场景
- 优先使用
thenReturn()的场景:- 返回值是固定常量,或只需预计算一次就可以复用的静态结果
- 不需要感知Mock方法的实际调用入参、调用上下文
- 无动态逻辑需求,追求单元测试执行效率
- 必须使用
thenAnswer()的场景:- 返回值需要和本次调用的入参联动,比如需要修改入参对象的字段后再返回
- 同一个Mock方法被多次调用时需要返回动态变化的结果(简单的顺序多返回值可使用
thenReturn(val1, val2)重载,但复杂逻辑仍需thenAnswer) - 需要在Mock方法被调用时执行额外的副作用逻辑,比如调用计数、日志打印、触发其他回调等
- 返回值的计算依赖调用时才能确定的上下文信息
直观示例对比:
假设要MockuserService.save(User user)方法,要求每次调用都把传入的user的id设为自增数值:// 错误写法:id只会在定义Stub时计算一次,后续所有调用返回的id都是1 long id = 1; User user = new User(); when(userService.save(any(User.class))).thenReturn(user.setId(id++)); // 正确写法:用thenAnswer实现每次调用动态生成id AtomicLong idGen = new AtomicLong(1); when(userService.save(any(User.class))).thenAnswer(invocation -> { User inputUser = invocation.getArgument(0); inputUser.setId(idGen.getAndIncrement()); return inputUser; });
内容的提问来源于stack exchange,提问作者Vasanthakumar Jagannathan
相关产品推荐
相关产品推荐

