Spring Mockito测试问题:saveAndFlush()未写入Mock仓库
解决Mockito Mock仓库调用
saveAndFlush()后无数据的问题 嗨,我来帮你捋清楚问题出在哪~
首先要明白:你用@Mock创建的AccountRepository是一个模拟对象,它本质上是个“假”仓库——Mockito的Mock对象所有方法默认都是空实现,要么返回null、要么返回空集合这类默认值。你直接调用repo.saveAndFlush(account)根本不会真的把数据存进去,因为这个方法的默认逻辑啥也没做。
再看你的测试方法list(),这里还有个逻辑倒置的问题:你写了when(underTest.list()).thenReturn(mockList),相当于直接给Controller的list()方法硬编码了返回值,完全跳过了list()方法内部调用repo.findAll()的真实逻辑。而mockList是repo.findAll()的结果(Mock默认返回空列表),所以你断言size() == 0自然会通过,但这根本没测试到Controller的真实行为。
修复方案&优化后的代码
我们调整测试逻辑,让它真正验证Controller的行为:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) // 替代手动初始化Mock,JUnit5标准用法 public class AccountTest { @InjectMocks private AccountController underTest; @Mock private AccountRepository repo; private Account account; @BeforeEach void setUp() { // 初始化测试用的Account对象 account = new Account(); account.setAccountNumber(6666L); account.setName("Steph"); } @Test void list_ShouldReturnAllAccounts() { // 告诉Mock仓库:当调用findAll()时,返回包含测试账户的列表 when(repo.findAll()).thenReturn(List.of(account)); // 真正调用Controller的list方法,获取返回结果 List<Account> result = underTest.list(); // 断言结果符合预期 assertEquals(1, result.size()); assertEquals("Steph", result.get(0).getName()); } // 额外加一个测试save逻辑的方法(如果你的Controller有save接口) @Test void save_ShouldCallRepositorySave() { // 调用Controller的save方法 underTest.save(account); // 验证Mock仓库的saveAndFlush方法确实被调用了一次,参数是我们的测试账户 verify(repo).saveAndFlush(account); } }
关键知识点总结
@Mock对象不会执行真实逻辑,必须用when(...).thenReturn(...)指定方法返回值,或者用verify()验证方法是否被调用。@InjectMocks会自动把Mock对象注入到被测试类(这里是AccountController),确保Controller调用的是我们的模拟仓库。- 测试的核心是调用被测试类的方法,然后断言返回结果,而不是直接给被测试方法硬设返回值——后者完全失去了测试的意义。
- 用
@ExtendWith(MockitoExtension.class)替代MockitoAnnotations.initMocks(this),是JUnit 5更简洁、规范的写法。
内容的提问来源于stack exchange,提问作者Stephanie Matheson
相关产品推荐
相关产品推荐

