ScalaMock:如何 mock/stub 一个方法来 return 每次调用不同的值?
ScalaMock: How to mock/stub a method to return different values per call?
使用 ScalaMock,我想 mock/stub 一个 class 方法,这样每次调用都会 return 不同的值(调用顺序很重要)。
我可以使用 mock
和 expects
实现此目的,但这将迫使我验证这些调用。
我可以用 stub
做到这一点吗?
此外,我怎样才能说出类似 "first time return X, and then always return 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.
使用 .noMoreThanOnce() 而不是 than.once() 很重要,否则会导致调用被验证。还有一个 .noMoreThanTwice() 方法,但我认为没有 .noMoreThanNTimes() 或任何等效方法。
以下是 "first time return X, and then always return 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")
对我来说,编写不验证调用且 returning 值取决于输入的模拟的最佳方法是使用 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(...)
的第一次调用将 return X
和每个连续的 Y
.
使用 ScalaMock,我想 mock/stub 一个 class 方法,这样每次调用都会 return 不同的值(调用顺序很重要)。
我可以使用 mock
和 expects
实现此目的,但这将迫使我验证这些调用。
我可以用 stub
做到这一点吗?
此外,我怎样才能说出类似 "first time return X, and then always return 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.
使用 .noMoreThanOnce() 而不是 than.once() 很重要,否则会导致调用被验证。还有一个 .noMoreThanTwice() 方法,但我认为没有 .noMoreThanNTimes() 或任何等效方法。
以下是 "first time return X, and then always return 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")
对我来说,编写不验证调用且 returning 值取决于输入的模拟的最佳方法是使用 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(...)
的第一次调用将 return X
和每个连续的 Y
.