【问题标题】:ScalaMock: How to mock/stub a method to return different values per call?ScalaMock:如何模拟/存根方法以每次调用返回不同的值?
【发布时间】:2015-12-08 17:39:07
【问题描述】:

使用 ScalaMock,我想模拟/存根一个类方法,以便每次调用都会返回不同的值(调用顺序很重要)。

我可以通过mockexpects 实现这一点,但这将迫使我验证这些调用。

我可以使用stub 来做到这一点吗?

另外,我怎么能说“第一次返回 X,然后总是返回 Y”(mockstub)?

【问题讨论】:

    标签: scala testing mocking scalamock


    【解决方案1】:

    是的,这是可以做到的,虽然语法有点不直观:

        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() 而不是 .once() 很重要,否则会导致调用被验证。还有一个 .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")
    

    【讨论】:

      【解决方案2】:

      对我来说,编写不验证调用且返回值取决于输入的模拟的最佳方法是使用 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-17
        • 1970-01-01
        • 1970-01-01
        • 2020-03-23
        • 1970-01-01
        • 2022-01-04
        相关资源
        最近更新 更多