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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala嘲弄由另一个特征扩展的特征相关的知识,希望对你有一定的参考价值。

我想测试一下

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

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

助手的定义如下:

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而不是一个真实的系统。

答案

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

你似乎在Helper周围使用像蛋糕模式这样的东西及其继承。如果是这样,您可以使用类而不是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中的所有调用执行操作,否则测试将无效。

以上是关于Scala嘲弄由另一个特征扩展的特征的主要内容,如果未能解决你的问题,请参考以下文章

Scala - 为使用数据库连接扩展特征/类的对象/单例编写单元测试

Scala 中的特征和抽象方法覆盖

用嘲弄来嘲弄 trait 方法

Scala在通用特征方法中找不到案例类参数

如何将参数注入Scala中的类/特征方法

在 Scala 中混合多个特征