You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA与Mockito:测试中save()返回null的原因及免Mock疑问

问题解答

为什么断言失败,save方法返回null?

Mockito创建的Mock对象,所有未显式指定行为的方法,默认会返回对应类型的"默认值":引用类型返回null,基本类型返回0/false等。你只Mock了findByUsername方法的行为,没有指定save方法的返回值,所以调用accountRepository.save(account)时,Mock对象会返回null,Service把这个null返回后,和你创建的new Account("floatfoo", "Egor")做相等比较,自然断言失败。

能不能不Mock save方法?

直接用普通Mock对象的话不行——因为默认返回null会导致Service返回null,断言还是会失败。但可以通过两种方式避免显式指定save的具体返回值:

  • 使用Mockito的Answer让save返回传入的参数:不用硬编码Account的属性,让Mock的save方法直接返回你传入的对象,这样Service返回的就是你创建的那个Account,断言就能通过。示例代码:
@Test
void createAccount_Should_Return_Account() throws InstanceAlreadyExistsException {
    AccountRepository ar  = mock(AccountRepository.class);
    when(ar.findByUsername("floatfoo")).thenReturn(Optional.empty());
    // 让save返回传入的参数
    when(ar.save(any(Account.class))).thenAnswer(invocation -> invocation.getArgument(0));
    AccountService as = new AccountService(ar);
    assertEquals(new Account("floatfoo", "Egor"), as.createAccount("floatfoo", "Egor"));
}
  • 使用Spy对象(如果你的AccountRepository是接口或可继承类):Spy会优先调用真实方法,只有显式Mock的方法才会被替换。但要注意,如果真实的save方法依赖数据库等外部资源,Spy可能会引发实际的数据库操作,这在单元测试中通常是不推荐的,所以还是用第一种方法更稳妥。

另外,你也可以给Mock对象设置全局默认行为,比如mock(AccountRepository.class, Mockito.RETURNS_SMART_NULLS),但这会影响所有未Mock的方法,不如针对性处理save方法清晰。

内容的提问来源于stack exchange,提问作者floatfoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:06:16