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

为何测试repository.delete()无需模拟?测试用例仍通过

为什么未模拟libraryRepository.delete(...)测试仍能通过?

先贴出你的代码:

@DeleteMapping(value = ["/library/books/{id}"])
fun deleteBook( @PathVariable("id") id: kotlin.Int): ResponseEntity<Unit> {
    return ResponseEntity(service.deleteBook(id), HttpStatus.valueOf(200))
}

override fun deleteBook(id: Int) {
    libraryRepository.findById(id).let {
        if(it == null){
            throw NotFoundException("Book with the given id not found")
        }
        libraryRepository.delete(it)
    }
}

@Test
fun `delete book and return 200`(){
    val library = Library(name = "testName", author = "testAuthor")
    `when`(libraryRepository.findById(1)).thenReturn(library)
    mvc.perform(MockMvcRequestBuilders.delete("/library/books/1"))
            .andExpect(MockMvcResultMatchers.status().isOk)
    verify(libraryRepository).delete(library)
}    

核心原因

Mockito 对无返回值(void)的方法有默认行为:当你没有主动模拟这类方法时,它不会抛出任何异常,只会执行空操作(什么都不做)。

你的libraryRepository.delete()是void方法,所以即使没写doNothing().when(libraryRepository).delete(any())这类模拟语句,代码调用到它时也不会中断流程——跳过实际删除逻辑后,代码正常走到返回200的步骤,自然能通过状态码校验。

另外,你测试用例里的verify(libraryRepository).delete(library)已经在验证delete方法是否被正确调用了,这其实已经覆盖了"代码执行到删除步骤"的关键逻辑,所以测试通过是完全合理的,你的预期(测试失败)本身是错误的。

补充说明

如果希望未被模拟的方法调用时抛出异常,可以开启Mockito的严格模式,比如在测试类上添加@MockitoSettings(strictness = Strictness.STRICT_STUBS),这样未存根的方法调用就会触发错误,符合你最初的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:55:22