Mockito:需要但未调用 Webflux Spring 启动

Mockito: Wanted but not invoked Webflux Spring boot

这似乎是 Whosebug 上的一个有据可查的问题,但似乎没有一个解决方案对我有用(如果我错了,如果有人指出我的解决方案,我会很高兴)。我正在关注 this tutorial 如何在 Spring 启动时测试 Webflux 控制器。我做了我认为正是教程中的内容,但出于某种原因,我收到以下错误:

    Wanted but not invoked:
wordRepository bean.save(
    Word(word=test word, id=0, updatedAt=2022-04-11T01:19:10.275631, createdAt=2022-04-11T01:19:10.275631)
);
-> at com.freeman.hangman.controller.WordControllerImplTest.givenWordDTO_expectedCreateWord(WordControllerImplTest.kt:78)
Actually, there were zero interactions with this mock.

Wanted but not invoked:
wordRepository bean.save(
    Word(word=test word, id=0, updatedAt=2022-04-11T01:19:10.275631, createdAt=2022-04-11T01:19:10.275631)
);
-> at com.freeman.hangman.controller.WordControllerImplTest.givenWordDTO_expectedCreateWord(WordControllerImplTest.kt:78)
Actually, there were zero interactions with this mock.

这是我的控制器

@ExtendWith(SpringExtension::class)
@WebFluxTest(WordControllerImpl::class)
@Import(WordServiceImpl::class)
class WordControllerImplTest {

    @Autowired
    lateinit var webClient: WebTestClient

    @MockBean
    lateinit var wordService: WordServiceImpl

    @MockBean
    lateinit var wordRepository: WordRepository


    private val CURRENT_DATE_TIME = LocalDateTime.now()
    private val TEST_WORD_ID = 1


    @Test
    @WithMockUser(username = "testuser@gmail.com", authorities = ["ROLE_USER", "ROLE_ADMIN"], password = "pwd")
    fun givenWordDTO_expectedCreateWord(){
        val wordDto = WordDto(word = "test word", id = 0, createdAt = CURRENT_DATE_TIME.toString())
        val word = Word("test word", 0, CURRENT_DATE_TIME, CURRENT_DATE_TIME)
        `when`(wordRepository.save(word)).thenReturn(Mono.just(word))

        webClient.mutateWith(csrf()).post()
            .uri("/freeman-hangman/words/create")
            .contentType(MediaType.APPLICATION_JSON)
            .body(BodyInserters.fromValue(wordDto))
            .exchange()
            .expectStatus()
            .isCreated

        verify(wordRepository, times(1)).save(word)//this is where the error is happening
    }

}

我哪里会出错?

如果我理解正确,WordServiceImplWordRepository 的包装器。对存储库的每次调用都通过服务。由于您已模拟该服务,因此这些操作不会进入存储库。

如果您想断言存储库交互,请不要模拟 WordServiceImpl 或改用间谍。

当您创建 class 的模拟对象时,您必须定义它的行为,因为模拟对象不充当 class 的原始实例。

你可以使用 spy 而不是 mock,如果你不通过模拟它的方法来告诉其他人,它的行为就像原始实例一样。

您可以执行以下任一操作:

  1. 删除@MockBean lateinit var wordService: WordServiceImpl
  2. WordServiceImpl
  3. 使用 @SpyBean 而不是 @MockBean

但如果我是你,我会选择第一个选项,因为对你没有使用的对象使用 @SpyBean 真的没有意义