我在Scala中具有以下功能
object MyService extends MyTrait {
def myMethod[T <% InvokableBuilder[MyClass]](builder: T): MyResponse = {
//do something
}
}
我正在尝试使用以下嘲讽来模拟此功能
val mockService = mock[MyTrait]
doReturn(info).when(mockService).myMethod(any())
我会收到以下错误,尽管我在函数中只有一个参数
org.mockito.exceptions.misusing.invaliduseofmatchersexception:对参数匹配者的使用无效! [INFO] 2个匹配者,有1个记录:
您的问题是:Scala是不是 Java。
您的隐式假设是:"那里的小鳞片方法被翻译成Java中的类似内容;因此,我可以简单地使用Mockito来处理它。
错误。您正在创建一个scala 对象在此处进行定义;如果我没记错的话; object 在scala中...在java中转换为 static (例如,请参见此处(。
因此,乍一看,您可能需要转向PowerMock(ITO(resp。jmockit是为了模拟这些静态元素。(还有我通常的警告:不要使用powermock;因为嘲笑静态的东西是 bad indue(。正如菲利普·M(Philipp M(在他的评论中指出的那样:嘲笑静态确实被认为是不良习惯。您应该宁愿在这里嘲笑事物的"特质"一面。
所以真正的答案是:您必须知道自己在做什么。Mockito是为 Java 编写的。您不能仅仅假设您在Scala中写下的任何东西,并且"看起来某种方式",例如Java可以很容易地映射到Mockito正在从事其工作的概念。
为了真正了解发生了什么;首先,您应该查看Scala编译器在您的情况下创建的类文件;查看方法签名;并为自己思考:"如果我不得不在Java源代码中调用该方法,我该怎么做?"从那里工作。
我更改了您的//做某事???因此,它将编译,然后在解析器阶段的末尾打印代码:
$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 Parser在上面如何执行此操作(。
漫长的示例:
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()
}
}