如何Mock Scala泛型方法?含隐式参数的方法Mock报错解决
解决Mockito Mock带上下文边界的泛型方法报错问题
你遇到的这个错误核心原因是Scala的上下文边界语法糖——[T: MyTrait]本质上是编译器自动给方法添加了一个隐式参数,所以你的bar方法实际的签名被展开成了:
def bar[T](id:Int, data: T, other:Option[String] = None)(implicit ev: MyTrait[T]): String
也就是说,这个方法有两个参数列表:第一个是(id, data, other),第二个是隐式的(ev: MyTrait[T])。而你在使用Mockito时只匹配了第一个参数列表的3个参数,漏掉了第二个参数列表里的隐式参数,所以才会报“4 matchers expected, 3 recorded”的错误。
修正方案:显式匹配隐式参数
你只需要在when调用里,给第二个参数列表也加上匹配器即可,有几种写法:
写法1:显式指定隐式参数的类型
implicit val myTrait = new MyTrait[String] {} val src = mock[Foo] // 显式匹配第二个参数列表的隐式MyTrait实例 when(src.bar(any(), any[String](), any())(any[MyTrait[String]]())).thenReturn("ok") src.bar(1, "some", None) // 现在可以正常执行了
写法2:简洁版(依赖类型推断)
如果编译器能自动推断出隐式参数的类型,也可以简化成:
implicit val myTrait = new MyTrait[String] {} val src = mock[Foo] when(src.bar(any(), any(), any())(any())).thenReturn("ok") src.bar(1, "some", None)
写法3:匹配特定的隐式实例
如果你想匹配某个具体的MyTrait实例(而不是任意实例),可以用eqTo:
implicit val myTrait = new MyTrait[String] {} val src = mock[Foo] when(src.bar(any(), any(), any())(eqTo(myTrait))).thenReturn("ok") src.bar(1, "some", None)
另一种风格:使用doReturn
如果你更习惯Mockito的doReturn语法,也可以这样写:
implicit val myTrait = new MyTrait[String] {} val src = mock[Foo] doReturn("ok").when(src).bar(any(), any(), any())(any()) src.bar(1, "some", None)
关键提醒
Mockito要求:要么所有参数都用匹配器(比如any()、eqTo()),要么所有参数都用具体值,不能混合使用。所以只要确保两个参数列表的所有参数都被正确匹配,就能解决这个问题。
内容的提问来源于stack exchange,提问作者zella
相关产品推荐
相关产品推荐

