Scala嘲弄由另一个特征扩展的特征

时间:2017-12-21 01:15:45

标签: scala mockito traits scalatest

我正在尝试测试

trait Name extends Helper {
    def name() = {
      var s = getSystem()
      s.name()
    }
}

我要做的就是确保" s.name()"通过模拟一个s的实例来调用方法,这是一个系统。

助手的定义如下:

trait Helper {
    def getSystem() : System = {
       systemGetter.get()
    }
}

截至目前,我的NameSpec看起来像:

class NameSpec extends FlatSpec with Matchers with MockitoSugar {

    class NameImpl extends Name
    var toTest = new NameImpl

    val mockSystem = mock[System]

    it should "call s.name() once" in {
        when(getSystem() is invoked, return a mockSystem) 
        toTest.name()
        // Verify that mockSystem.name() happened only once
    }
}

我感到困惑的是当它调用getSystem()时如何在toTest.name()中返回一个模拟系统,以便我可以验证系统只调用一次s.name()。如果它是Name trait中name()方法的参数,我可以很容易地模拟这个系统,所以我想我不知道如何注入"调用该方法时使用的mockSystem代替实际系统。

1 个答案:

答案 0 :(得分:0)

不幸的是,您的代码无法编译,因此显然不足以代表您的真实情况。特别是不清楚Helper如何真正获得System类型的对象。我认为在实际代码中你应该模拟systemGetter,我想这是以某种方式注入到实现Helper特征的对象中,以返回你的mockSystem。但是,很难根据您提供的代码向您展示有效的示例。如果出于某种原因,这不是你能做的,还有一些途径。

你似乎在Helper周围使用Cake模式及其继承。如果是这样,您可以使用类而不是NameImpl来注入System

class NameWithInjectedSystem(val system: System) extends Name {
  override def getSystem(): System = system
}

it should "call s.name() once" in {
  val mockSystem = mock[System]
  val nameToTest = new NameWithInjectedSystem(mockSystem)
  val mockName = "Mock name"

  when(mockSystem.name()).thenReturn(mockName)
  val actual = nameToTest.name()
  actual should === (mockName)
  verify(mockSystem, times(1)).name()
}

最后你甚至可以模拟nameToTest对象本身,但这不是我建议的方式,因为它将测试绑定到比你想要的更多的实现细节:

it should "call s.name() once" in {
  val mockSystem = mock[System]
  val nameToTest = mock[NameImpl]
  when(nameToTest.getSystem()).thenReturn(mockSystem)
  when(nameToTest.name()).thenCallRealMethod()
  val mockName = "Mock name"
  when(mockSystem.name()).thenReturn(mockName)
  val actual = nameToTest.name()
  actual should ===(mockName)
  verify(mockSystem, times(1)).name()
}

请注意,您必须为thenCallRealMethod电话拨打.name(),因此您应该对name内的所有电话进行操作,否则测试将无效。