ScalaMockを使用して、クラスメソッドをモック/スタブして、呼び出しごとに異なる値を返すようにします(呼び出しの順序が重要です)。
これはmock
とexpects
で実現できますが、それではこれらの呼び出しを確認する必要があります。
stub
でこれを行うことはできますか?
また、「最初にXを返し、次に常にYを返す」(両方ともmock
とstub
を使用)のように言うにはどうすればよいですか?
はい、これは可能ですが、構文は少し直感的ではありません。
trait Foo { def getInt: Int }
val fooStub = stub[Foo]
(fooStub.getInt _).when().returns(1).noMoreThanOnce()
(fooStub.getInt _).when().returns(2).noMoreThanOnce()
(fooStub.getInt _).when().returns(3)
(fooStub.getInt _).when().returns(4)
assert(fooStub.getInt == 1)
assert(fooStub.getInt == 2)
assert(fooStub.getInt == 3)
// Note that it's fine that we don't call it a fourth time - calls are not verified.
.once()ではなく.noMoreThanOnce()を使用することが重要です。そうしないと、呼び出しが検証されます。 .noMoreThanTwice()メソッドもありますが、.noMoreThanNTimes()または同等のものはないと思います。
モックとスタブに対して「最初にXを返し、次に常にYを返す」方法は次のとおりです。
trait Bar { def getString: String }
val barMock = mock[Bar]
(barMock.getString _).expects().returning("X")
(barMock.getString _).expects().returning("Y").anyNumberOfTimes()
assert(barMock.getString == "X")
assert(barMock.getString == "Y")
assert(barMock.getString == "Y")
val barStub = stub[Bar]
(barStub.getString _).when().returns("x").noMoreThanOnce()
(barStub.getString _).when().returns("y")
assert(barStub.getString == "x")
assert(barStub.getString == "y")
assert(barStub.getString == "y")
私にとって、呼び出しを検証せず、戻り値が入力に依存するモックを作成する最良の方法は、onCall
メソッドを使用することです。これは関数のクロージャーを取ります。デフォルトでは、最初の呼び出しのみが処理されるため、必ずanyNumberOfTimes
またはrepreted(...)
を追加してください。
_import org.scalamock.scalatest.MockFactory
trait Foo {
def getSomeValue(param1: Any, param2: Any): String
}
class Test extends MockFactory {
val fooMock = stub[Foo]
val it = Iterator.single("X") ++ Iterator.continually("Y")
(fooMock.getSomeValue _)
.expects(*, *)
.onCall((p1, p2) => it.next())
.anyNumberOfTimes
}
_
これで、fooMock.someValue(...)
を最初に呼び出すと、X
と連続する各Y
が返されます。