【问题标题】:Scala - Is there a way to mock trait, extended by companion object?Scala - 有没有办法模拟特征,由伴生对象扩展?
【发布时间】:2016-03-08 07:57:39
【问题描述】:

我在我的小项目中使用 scalatest 和 scalamock。我创建了一个 trait 和一个类,以及它的伴生对象。

trait A{
 def getSomething(arg1)
}

class B(field1)....

object B extends A{
 def apply(arg1) = new B(getSomething(arg1))
}

代码运行良好,但在测试此代码时出现问题。单元测试应该是独立的,因此我应该以某种方式模拟/存根特征 A:

val fakeA = stub[A]    
(fakeA.getSomething _).when(arg).returns(res)

现在......我应该如何在我的单元测试中使用这个模拟特征?模拟创建一个对象(不是类型),并且使用这样的代码我无法将它“传递”给我的对象(或使用)。我怎样才能实现我的目标(在我的 B 对象中存根/模拟 getSomething())?我试图将对象 B 拆分为 Blogic 和 B 扩展 Blogic。但是然后呢?

【问题讨论】:

  • 您实际上要在这里测试哪种逻辑?谁在使用 mocked 方法?
  • 模拟的方法将用于我的单元测试。在这里我想测试一下,apply 方法是否创建了有效的对象(即,它为我的 B 类的正确字段分配了正确的值(由我试图模拟的方法返回)。
  • 然后做new B(whateverYourMockWouldReturn),然后测试一下。

标签: scala scalatest scalamock


【解决方案1】:

Scala 中的对象是单例实例,意味着“世界末日”。它们不能被继承、嘲笑(没有黑客)或其他任何东西。您有以下选择:

  1. 直接测试您的对象,即调用B.apply(...) 并将结果测试为您的预期结果。
  2. 将对象功能提取到特征/类中,然后将所有功能混合在一起

第二种解决方案的示例

trait A{
  def getSomething(arg1: Int): Int = ???
}

trait BFactoryUsingA { self: A => // This says that it needs/requires A
  def apply(arg1: Int) = new B(getSomething(arg1))
}

class B(field1: Int) {}

object B extends BFactoryUsingA with A {
  // No methods or those which have nothing to do with traits A and BFactoryUsingA hierarchy and composition
}

在你的测试中你现在可以写:

// Instance as anonymous mixin of traits containing logic
val instanceUnderTest = new BFactoryUnsingA with A { }

我不能说你是否有能力和奢侈将你的对象分解成特征。大多数情况下,它是可行的,没有太多麻烦,但你的里程可能会有所不同。这种解决方案的另一个优点是根本不需要模拟。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2012-12-11
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多