Spring Boot3+MongoDB的JUnit测试中Strict stubbing参数不匹配问题
解决Mockito Strict Stubbing参数不匹配问题
问题场景
基于Spring Boot 3.3.3和MongoDB编写JUnit测试时,运行TestNoteService的createNoteTest方法抛出org.mockito.exceptions.misusing.PotentialStubbingProblem异常,提示Strict stubbing参数不匹配:save方法实际调用传入的Note对象id为5f3623af,但存根配置使用的Note对象id为sghgak17,二者不一致。
相关代码如下:
Note实体类
@Document(collection = "Notes") public class Note { @Id private String id; //(auto-generated UUID or MongoDB ObjectId) private String title; private String content; private LocalDateTime createdAt; private LocalDateTime updatedAt; // 省略getter、setter、builder等方法 }
TestNoteService测试类
@ExtendWith(MockitoExtension.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class TestNoteService { @Mock private NotesRepository notesRepository; @InjectMocks private NoteService noteService; private Note note; @BeforeEach public void setup() { note = Note.builder() .id("sghgak17") .title("Title") .content("Testing Content.") .createdAt(LocalDateTime.now()) .updatedAt(LocalDateTime.now()) .build(); } @Test @Order(1) public void createNoteTest() { given(notesRepository.save(note)).willReturn(note); Note savedNote = noteService.createNote(note); System.out.println(savedNote); } }
解决方案
1. 使用任意对象匹配器(最常用)
将存根中的具体Note对象替换为any(Note.class),Mockito会匹配任意传入的Note实例,不再严格校验对象的所有属性:
@Test @Order(1) public void createNoteTest() { // 匹配任意Note对象 given(notesRepository.save(any(Note.class))).willReturn(note); Note savedNote = noteService.createNote(note); assertThat(savedNote).isNotNull(); }
2. 自定义参数匹配逻辑(精准匹配)
如果需要校验除id外的其他属性是否匹配,可以使用argThat自定义匹配规则,忽略自动生成的id字段:
@Test @Order(1) public void createNoteTest() { given(notesRepository.save(argThat(n -> n.getTitle().equals(note.getTitle()) && n.getContent().equals(note.getContent()) && n.getCreatedAt() != null && n.getUpdatedAt() != null ))).willReturn(note); Note savedNote = noteService.createNote(note); assertThat(savedNote).isNotNull(); }
3. 修正测试数据与业务逻辑匹配
检查NoteService的createNote方法实现,大概率是该方法在保存前自动生成了新的id(比如UUID或MongoDB自动生成的ObjectId),此时测试代码不应手动设置id:
- 修改
setup方法,移除手动设置id的代码:
@BeforeEach public void setup() { note = Note.builder() .title("Title") .content("Testing Content.") .createdAt(LocalDateTime.now()) .updatedAt(LocalDateTime.now()) .build(); // 不再手动设置id }
- 存根时使用任意对象匹配器或自定义匹配逻辑即可。
4. 临时关闭Strict Stubbing(不推荐)
如果只是临时绕过该校验,可以在测试类上添加@MockitoSettings(strictness = Strictness.LENIENT)关闭Strict Stubbing模式,但这会隐藏潜在的参数不匹配问题,仅作为应急方案:
@ExtendWith(MockitoExtension.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @MockitoSettings(strictness = Strictness.LENIENT) // 关闭Strict Stubbing public class TestNoteService { // ... 测试代码不变 }
内容的提问来源于stack exchange,提问作者Ganna
相关产品推荐
相关产品推荐

