mockito check/match 参数值是否在验证中

Does mockito check/match argument values in verify

在这个测试用例中,我想检查一个函数是否调用了特定的编号。具有特定值的次数

    "add tag information in supported tags" in {
          val servicesTestEnv = new ServicesTestEnv(components = components)
    
          val questionTransactionDBService = new QuestionsTransactionDatabaseService(
            servicesTestEnv.mockAnswersTransactionRepository,
            servicesTestEnv.mockPartitionsOfATagTransactionRepository,
            servicesTestEnv.mockPracticeQuestionsTagsTransactionRepository,
            servicesTestEnv.mockPracticeQuestionsTransactionRepository,
            servicesTestEnv.mockSupportedTagsTransactionRepository,
            servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository,
            servicesTestEnv.mockQuestionsCreatedByUserRepo,
            servicesTestEnv.mockTransactionService,
            servicesTestEnv.mockPartitionsOfATagRepository,
            servicesTestEnv.mockHelperMethods
          )
          when(servicesTestEnv.mockTransactionService.start)
            .thenReturn(servicesTestEnv.mockDistributedTransaction)
    
          doNothing().when(servicesTestEnv.mockPracticeQuestionsTransactionRepository).add(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[PracticeQuestion],ArgumentMatchers.any[MutationCondition])
          doNothing().when(servicesTestEnv.mockPracticeQuestionsTagsTransactionRepository).add(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[PracticeQuestionTag],ArgumentMatchers.any[MutationCondition])
          when(servicesTestEnv.mockPartitionsOfATagTransactionRepository.get(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[TagPartitionKeys]))
            .thenReturn(Right(servicesTestEnv.questionTestEnv.tagPartitions))
          doNothing().when(servicesTestEnv.mockPartitionsOfATagTransactionRepository).add(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[TagPartitions],ArgumentMatchers.any[MutationCondition])
          doNothing().when(servicesTestEnv.mockQuestionsCreatedByUserRepo).add(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[QuestionsCreatedByAUserForATag],ArgumentMatchers.any[MutationCondition])
          when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository.get(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[ExternalUserProfileKeys]))
            .thenReturn(Right(servicesTestEnv.externalUserProfileWithTags))
          doNothing().when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository).update(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[ExternalUserProfile])
          doNothing().when(servicesTestEnv.mockDistributedTransaction).commit()
          when(servicesTestEnv.mockSupportedTagsTransactionRepository.get(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[SupportedTagsKeys]))
            .thenReturn(Left(SupportedTagNotFoundException()))
          val supportedTagInfo = SupportedTag("coding","javascript1","empty")
          logger.trace(s"will compare with ${supportedTagInfo}")
          val result = questionTransactionDBService.newQuestion(servicesTestEnv.questionTestEnv.practiceQuestion,servicesTestEnv.questionTestEnv.practiceQuestionTag,servicesTestEnv.user)
          verify(servicesTestEnv.mockSupportedTagsTransactionRepository,times(0))
            .add(servicesTestEnv.mockDistributedTransaction,supportedTagInfo)
        }

如果我将 supportedTagInfo 的值更改为 val supportedTagInfo = SupportedTag("coding","javascript-something else","empty"),测试用例仍然通过。

在痕迹中,我可以看到两次都使用了标签 coding-javascript-empty。此值来自 servicesTestEnv.questionTestEnv.practiceQuestionTag,这对两个测试用例都是通用的,并在

处提供
val result = questionTransactionDBService.newQuestion(servicesTestEnv.questionTestEnv.practiceQuestion,servicesTestEnv.questionTestEnv.practiceQuestionTag,servicesTestEnv.user)

TRACE - saving coding-javascript-empty in supported tag information

是我做错了什么还是 Mockito 没有检查参数值?

更新 我尝试在 Scala 中使用 ArgumentCaptor 但我很挣扎。

我创建了 class 的 mock 作为

val mockSupportedTagsTransactionRepository = mock(classOf[SupportedTagsTransactionRepository])

我正在调用 mock 的 add 方法。它的签名是

def add(transaction:DistributedTransaction,supportedTag:SupportedTag,mutationCondition:MutationCondition = new PutIfNotExists()) = {...} 

我调用了上述模拟的 getadd 方法。我将他们的行为定义为

          when(servicesTestEnv.mockSupportedTagsTransactionRepository.get(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[SupportedTagsKeys]))
            .thenReturn(Left(SupportedTagNotFoundException()))

然后我创建所需的 ArgumentCaptor

       val argumentCaptor2 = ArgumentCaptor.forClass(classOf[SupportedTag])
       val argumentCaptor3 = ArgumentCaptor.forClass(classOf[MutationCondition])

然后调用测试中的函数

verify(servicesTestEnv.mockSupportedTagsTransactionRepository ,times(1))
            .add(argumentCaptor1.capture(),argumentCaptor2.capture(),argumentCaptor3.capture())
          logger.trace(s"capture 1 ${argumentCaptor1.getAllValues}")
          logger.trace(s"capture 2 ${argumentCaptor2.getAllValues}")
          logger.trace(s"capture 3 ${argumentCaptor3.getAllValues}")

然后我查看结果

val argumentsInvoked = argumentCaptor2.getAllValues
          argumentsInvoked.contains(supportedTagInfo)

必须为真

但是 argumentsInvoked 类型是 List[Nothing] 而不是 List[SupportedTag]

正确的方法是同时指定参数的类型

val argumentCaptor1 = ArgumentCaptor.forClass(classOf[DistributedTransaction])
      val argumentCaptor2 = ArgumentCaptor.forClass[SupportedTag,SupportedTag](classOf[SupportedTag]) //Note two types. First is type of argument, second is type of class. They are the same in my case. 
      val argumentCaptor3 = ArgumentCaptor.forClass(classOf[MutationCondition])

      verify(servicesTestEnv.mockSupportedTagsTransactionRepository ,times(1))
        .add(argumentCaptor1.capture(),argumentCaptor2.capture(),argumentCaptor3.capture())
      val argumentsInvoked = argumentCaptor2.getAllValues //this now returns List[SupportedTag]
      argumentsInvoked.size mustBe 1
      val argument = argumentsInvoked.get(0)
      argument.course mustBe supportedTagInfo.course
      argument.subject mustBe supportedTagInfo.subject
      argument.topic mustBe supportedTagInfo.topic