如何在存根上调用真正的方法

How to call real method on a stub

有没有办法用 scalamock 在存根对象上调用真正的方法?

我希望能够做这样的事情:

class MySpec extends FunSpec with Matchers with MockFactory {
  trait MyTrait {
    def f1: Int
    def f2: Int = f1
  }

  describe("my feature") {
    it("should work") {
      val t = stub[MyTrait]
      (t.f1 _).when().returns(15)
      // I would like to do the following:
      // (t.f2 _).when().callRealMethod()
      t.f2 should be (15)
    }
  }
}

注意:我能够通过将 f2 设置为 final 来解决这个问题,但我想知道是否有一种方法可以在不更改被测代码的情况下做到这一点。

不幸的是,间谍不可用: https://github.com/paulbutcher/ScalaMock/issues/249

不幸的是,ScalaMock 不提供 «callRealMethod» 功能。

如果有可能更改测试框架,您可以使用 mockito-scalaMockitoSugar 特性来提供替代方法你与你想要的。

您的代码将如下所示:

class MySpec extends FunSpec with MockitoSugar with Matchers {

  trait MyTrait {
    def f1: String = "mock"

    def f2: String = "not a mock"
  }


  describe("my feature") {
    it("should work") {
      val t = mock[MyTrait]
      when(t.f1).thenReturn("mocked")
      t.f1 shouldBe "mocked"
      when(t.f2) thenCallRealMethod()
      t.f2 shouldBe "not a mock"
    }
  }

您需要添加 mockito scala 作为依赖项。 (sbt 方式)

 "org.mockito" %% "mockito-scala" % "${version}",
 "org.mockito" %% "mockito-scala-scalatest" % "${version}"

我推荐的模式是按照您的建议将您不想模拟的函数设为最终函数。但是,与其在真实代码中执行此操作,不如使用仅用于测试目的的子类,例如像这样:

import org.scalamock.scalatest.MockFactory
import org.scalatest.FunSuite
import PartialMockingTest._

class PartialMockingTest extends FunSuite with MockFactory {

  test("test case") {

    class PartFinalCls extends Cls {
      override final def B(): Int = super.B()
    }

    val f = stub[PartFinalCls]
    f.A _ when 7 returns 5
    assert(f.B() == 6)
  }

}

object PartialMockingTest {
  class Cls {
    def A(dummy: Int): Int = 5

    def B(): Int = A(7) + 1
  }
}