Sas*_*lla 0 scala implicit mockito
我可以Foo通过隐式类使用其他方法扩展我的 Scala类:
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是我可以模拟这些方法吗?
import org.mockito.Mockito
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
import FooExtensions.implicits._
val foo = mock[Foo]
Mockito.when(foo.baz).thenReturn("bix") // fails at runtime
}
}
}
Run Code Online (Sandbox Code Playgroud)
这编译,但失败
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Run Code Online (Sandbox Code Playgroud)
是否可以模拟通过隐式类添加的方法?希望与 Mockito (或mockito-scala),但我对任何有效的方法感兴趣。
关于扩展方法,它们基本上是一种语法糖:
trait Foo
implicit class ExtensionMethods(foo: Foo) {
def bar: String = "bar
}
foo.bar
Run Code Online (Sandbox Code Playgroud)
等于
new ExtensionMethods(foo).bar
Run Code Online (Sandbox Code Playgroud)
这么嘲讽:
Mockito.when(foo.bar).thenReturn("bix")
Run Code Online (Sandbox Code Playgroud)
变成:
Mockito.when(new ExtensionMethods(foo).bar).thenReturn("bix")
Run Code Online (Sandbox Code Playgroud)
我认为没有解决方法-也许 PowerMock 可以让您更改类构造函数...,但是使用普通的 Mockito 是不可能的。
通常,这不是问题。那是因为:
如果行为应该改变,则在类型类中实现它,并使扩展方法使用该类型类来注入行为
trait Bar {
def bar: String
}
object Bar {
implicit val defaultBar: Bar = new Bar { def bar = "bar" }
}
implicit class ExtensionMethods(foo: Foo) {
def bar(implicit bar: Bar): String = bar.bar
}
// in test
implicit var overridenBar: Bar = ...
assert(foo.bar === "sth")
Run Code Online (Sandbox Code Playgroud)附带说明:您获得的功能越多,您需要模拟的东西就越少,因为一切都将仅取决于内部传递的输入,并且一连串的模拟将变成一种代码味道 - 耦合太紧,接口太大等。问题是许多 Java 库甚至不遵循 SOLID 原则,这使得它们既难以使用 FP 进行使用/测试,也难以单独使用糟糕的 OOP。如果你觉得嘲笑是你的情况的唯一途径,我会告诉你这个。