我在Scala中有一个函数,如下所示
object MyService extends MyTrait {
def myMethod[T <% InvokableBuilder[MyClass]](builder: T): MyResponse = {
//do something
}
}
我正在尝试使用mockito来模拟此功能,如下所示
val mockService = mock[MyTrait]
doReturn(info).when(mockService).myMethod(any())
虽然函数
中只有一个参数,但我收到以下错误org.mockito.exceptions.misusing.InvalidUseOfMatchersException:参数匹配器的使用无效! [info] 2匹配预期,1记录:
答案 0 :(得分:1)
你的问题是:scala 不是 java。
你的隐含假设是:&#34;那里的小scala方法被翻译成类似于Java的东西;因此我可以简单地使用mockito来处理那个&#34;。
错误。您正在此处创建scala 对象定义;如果我没记错的话; scala中的 object ...转换为Java中的 static (例如,请参阅here)。
因此,乍一看,您可能需要转向PowerMock(ito)。 JMockit是为了模拟那些静态元素。 (以及我通常的警告:不要使用PowerMock;因为嘲弄静态内容是糟糕的想法)。正如Philipp M在他的评论中指出的那样:嘲笑静态真的被认为是不好的做法。你应该考虑嘲笑&#34; trait&#34;事情的一面。
所以真正的答案是:你必须知道自己在做什么。 Mockito是为 java 编写的。你不能只假设你在scala中记下的任何东西,并且&#34;看起来不知何故&#34;像Java一样可以很容易地映射到Mockito正在开展工作的概念。
为了真正了解正在发生的事情;您应首先查看scala编译器在您的案例中创建的类文件;查看方法签名;并为自己思考:&#34;如果我必须在java源代码中调用该方法,我该怎么做?&#34;并从那里开始工作。
答案 1 :(得分:0)
我改变了你的//做了什么?所以它会编译,然后在解析器阶段结束时打印代码:
$scalac MyService.scala -Xprint:parser
[[syntax trees at end of parser]] // MyService.scala
package <empty> {
object MyService extends MyTrait {
def <init>() = {
super.<init>();
()
};
def myMethod[T](builder: T)(implicit evidence$1:_root_.scala.Function1[T,InvokableBuilder[MyClass]]): MyResponse = $qmark$qmark$qmark
}
}
如您所见,由于您的视图绑定,myMethod有第二个参数列表。 我不确定你会如何用Mockito来嘲笑它,但我建议你试试ScalaMock。
注意:不推荐使用视图边界 - 我建议用隐式参数替换它们(请参阅scalac解析器如何执行上述操作)。
龙的例子:
import org.scalamock.scalatest.MockFactory
import org.scalatest.FlatSpec
import scala.language.implicitConversions
class FooTest extends FlatSpec with MockFactory {
trait MyTrait {
def myMethod[T](builder: T)(implicit ev$1: T => InvokableBuilder[MyClass]): MyResponse
}
trait InvokableBuilder[T]
class MyClass
class MyResponse
class Foo
object MyService extends MyTrait {
def myMethod[T](builder: T)(implicit ev$1: T => InvokableBuilder[MyClass]): MyResponse = {
//do something
???
}
}
behavior of "Foo"
it should "foo" in {
val x = mock[MyTrait]
implicit val fooConvert: Foo => InvokableBuilder[MyClass] = ???
(x.myMethod(_: Foo)).expects(*).once()
}
}