如何在 Scala 中模拟带有函数参数的方法? [英] How to mock a method with functional arguments in Scala?

查看:22
本文介绍了如何在 Scala 中模拟带有函数参数的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试模拟一个采用按名称调用参数的方法调用:

导入 org.scalatest.WordSpec导入 org.scalatest.mock.MockitoSugar导入 org.mockito.Mockito._导入 org.junit.runner.RunWith导入 org.scalatest.junit.JUnitRunner特质合作者{def doSomething(t: => 东西)}特质事物@RunWith(classOf[JUnitRunner])类 Test 使用 MockitoSugar { 扩展 WordSpec被测对象"应{{中的呼叫合作者"//设置val m = mock[合作者]val t = mock[东西]//测试代码:这实际上会被 SUT 调用m.doSomething(t)//验证调用验证(m).doSomething(t)}}}

我主要对 Mockito 感兴趣,因为我正在使用它,但我很想看看是否有任何主要的模拟框架能够进行这种测试.测试在运行时在 verify 行失败,出现类似

的错误<块引用>

参数不同!通缉:合作者.doSomething(($anonfun$apply$3) <函数>);->在测试$$anonfun$1$$anonfun$apply$1.apply(Test.scala:27​​)实际调用有不同的参数:合作者.doSomething(($anonfun$apply$2) <函数>);->在测试$$anonfun$1$$anonfun$apply$1.apply(Test.scala:24)

如果我对情况的理解正确,编译器会将 t 隐式包装在一个返回 t 的空函数中.然后,模拟框架将该函数与测试代码中生成的函数进行比较,该函数是等效的,但不是 equals().

我的情况是这个问题的一个相对简单的版本,但我认为这对于任何高阶函数都是一个问题.

解决方案

这看起来很难看,但希望它可以帮助你找到好的解决方案:

导入 org.scalatest.mock.MockitoSugar导入 org.mockito.Mockito._特质合作者{def doSomething(t: => 东西)}特质事物新的 MockitoSugar {//设置val m = mock[合作者]val t = mock[东西]m.doSomething(t)classOf[Collaborator].getMethod("doSomething", classOf[Function0[_]]).invoke(验证(m),新功能0 [事物] {def 应用() = 空覆盖 def equals(o: Any): Boolean = t == o.asInstanceOf[Function0[Thing]].apply()})}

I'm trying to mock a method call that takes a call-by-name argument:

import org.scalatest.WordSpec
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

trait Collaborator {
   def doSomething(t: => Thing)
}

trait Thing

@RunWith(classOf[JUnitRunner])
class Test extends WordSpec with MockitoSugar {
   "The subject under test" should {
      "call the collaborator" in {
         // setup
         val m = mock[Collaborator]
         val t = mock[Thing]

         // test code: this would actually be invoked by the SUT
         m.doSomething(t)

         // verify the call
         verify(m).doSomething(t)
      }
   }
}

I'm primarily interested in Mockito since that's what I'm using, but I'd be interested to see whether any of the major mock frameworks is capable of this kind of testing. The Test fails at runtime on the verify line, with an error like

Argument(s) are different! Wanted:  
collaborator.doSomething(  
   ($anonfun$apply$3) <function>  
);  
-> at Test$$anonfun$1$$anonfun$apply$1.apply(Test.scala:27)  
Actual invocation has different arguments:  
collaborator.doSomething(  
    ($anonfun$apply$2) <function>  
);  
-> at Test$$anonfun$1$$anonfun$apply$1.apply(Test.scala:24)  

If I'm understanding the situation correctly, the compiler is implicitly wrapping t in a nullary function that returns t. The mock framework is then comparing that function to the one produced in the test code, which is equivalent but not equals().

My case is a relatively simple version of the problem, but I think this would be an issue with any higher-order function.

解决方案

This looks ugly, but hopefully it can help you to find good solution:

import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._

trait Collaborator {
   def doSomething(t: => Thing)
}

trait Thing

new MockitoSugar {
     // setup
     val m = mock[Collaborator]
     val t = mock[Thing]

     m.doSomething(t)

     classOf[Collaborator].getMethod("doSomething", classOf[Function0[_]]).invoke(
        verify(m), 
        new Function0[Thing] { 
            def apply() = null
            override def equals(o: Any): Boolean = t == o.asInstanceOf[Function0[Thing]].apply() 
      })
}

这篇关于如何在 Scala 中模拟带有函数参数的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆