【问题标题】:Can you capture and inspect arguments supplied to a method under test with ScalaMock?您可以使用 ScalaMock 捕获和检查提供给被测方法的参数吗?
【发布时间】:2012-09-04 08:06:32
【问题描述】:

Java Mocking 框架 Mockito 有一个名为 ArgumentCaptor 的实用程序类,它会在多次调用验证方法时累积值列表。

ScalaMock 有类似的机制吗?

【问题讨论】:

    标签: scala mocking scalatest


    【解决方案1】:

    preview release of ScalaMock3 中有一个底层机制可以做到这一点,但它目前不暴露给客户端代码。

    你的用例是什么?

    您可以通过使用whereonCall 记录的here(分别在“谓词匹配”和“返回值”标题下)来实现所需的功能。

    【讨论】:

    • 好问题。该用例正是您使用ArgumentCaptors 的目的:确保调用序列准确地传递您期望的值。我认为最终使用onCall 来积累结果列表,然后再对其进行验证。
    • “这里”的链接现在已断开。也许scalamock.org/user-guide/advanced_topics 是一个合适的替代品。
    • @Paul 这是否已添加到 ScalaMock 4.x 中?我觉得参数匹配并不完全是参数捕获。
    • 我已将 ScalaMock 的维护工作交给 Philipp Meyerhoefer github.com/barkhorn
    【解决方案2】:

    Specs2 中,您可以使用以下内容:

    myMock.myFunction(argument) answers(
        passedArgument => "something with"+passedArgument
    )
    

    这在引擎盖下映射到 Mockito 的 ArgumentCaptor。

    【讨论】:

    • 这样passedArgument的类型是Any。有没有办法在闭包内维护其类型信息?这样我必须强制转换它才能使用它的成员。
    • 我认为你必须声明类型。 passedArgument:Mine => … 对我来说就像它得到的一样好,当然不用做真正的工作。
    【解决方案3】:

    根据the Mockito documentation,可以直接使用specs2匹配器,例如

    val myArgumentMatcher: PartialFunction[ArgumentType, MatchResult[_]] = {
      case argument => argument mustEqual expectedValue
    }
    there was one(myMock).myFunction(beLike(myArgumentMatcher))
    

    这个解决方案很酷的一点是,部分函数提供了非常大的灵活性。你可以对你的参数进行模式匹配等。当然,如果你真的只需要比较参数值,那么就不需要偏函数,你可以这样做

    there was one(myMock).myFunction(==_(expectedValue))
    

    【讨论】:

      【解决方案4】:

      另一种选择是通过扩展现有的匹配器来实现您自己的参数捕获器。那种东西应该可以解决问题(对于scalamock 3):

      trait TestMatchers extends Matchers {
      
          case class ArgumentCaptor[T]() {
              var valueCaptured: Option[T] = None
          }
      
          class MatchAnyWithCaptor[T](captor: ArgumentCaptor[T]) extends MatchAny {
              override def equals(that: Any): Boolean = {
                 captor.valueCaptured = Some(that.asInstanceOf[T])
                 super.equals(that)
              }
          }
      
          def capture[T](captor: ArgumentCaptor[T]) = new MatchAnyWithCaptor[T](captor)
      }
      

      您可以通过将该特征添加到您的测试类来使用这个新的匹配器

      val captor = new ArgumentCaptor[MyClass]
      
      (obj1.method(_: MyClass)).expects(capture(captor)).returns(something)
      
      println(captor.capturedValue)
      

      【讨论】:

        【解决方案5】:

        使用ArgumentCapture

        val subject = new ClassUnderTest(mockCollaborator)
        // Create the argumentCapture
        val argumentCapture = new ArgumentCapture[ArgumentClazz]
        
        // Call the method under test
        subject.methodUnderTest(methodParam)
        
        // Verifications
        there was one (mockCollaborator).someMethod(argumentCapture)
        val argument = argumentCapture.value
        argument.getSomething mustEqual methodParam
        

        【讨论】:

          猜你喜欢
          • 2011-08-24
          • 2020-11-26
          • 1970-01-01
          • 2023-04-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多