模拟Scala对象和函数

noo*_*ber 3 unit-testing scala mocking

我有一个Scala对象,它包含一些实用程序功能.这些函数由同一对象中存在的其他函数或其他类/对象调用.是否可以模拟这个对象或函数,以便我可以对它们被调用的类进行单元测试.

例:

object Util {

  def methodA() = { 
    //other code
    methodB() 
    //other code
  }

  def methodB() = { 
    //other code
    methodC() 
    //other code
  }

  def methodC() = { ... }

}
Run Code Online (Sandbox Code Playgroud)

在这里,我从另一个类调用对象函数

class Data {

  //other code

  def call() = {
    //other code
    Util.methodA()
    //other code
  }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能对类Data的函数call()进行单元测试?在Java中,我可以为Util创建一个模拟对象,并设置对methodA()调用的期望,但这在Scala中是不可能的,因为没有模拟库支持模拟Scala对象.

Kei*_*rom 6

从某种意义上说,问题在于你使用的模式类似于Java中的静态类.你不能模拟静态类,这就是Java模式通常不支持这种方法的原因.

另一方面,在Scala你可以.Make Util扩展特性并实现它.

trait UtilityMethods {
 def methodA()
 def methodB()
}

object Utils extends UtilityMethods {
  def methodA() = {}
  def methodB() = {}
}
Run Code Online (Sandbox Code Playgroud)

然后在你的测试中:

val mockedUtils = mock[UtilityMethods]
Run Code Online (Sandbox Code Playgroud)

(使用mockito).显然你必须在代码而不是Utils周围传递UtilityMethods,就像你在Java中使用接口一样.

通常,您也可以使用隐式作用域来注入函数,从而在没有类似静态的对象方法的情况下模拟这些依赖项,但上面的内容非常接近Java模式,应该感觉很舒服.

  • 当然。有几种解决方法。我在寻找DI方法时经常使用隐式,因为它们是相似的模式-由外部参与者注入的提供的依赖项。在这种情况下,请考虑使用“类Data(implicit utils:UtilityMethods)”,然后进行其余操作-在需要的地方提供您对UtilityMethods的实现。您还可以使用[隐式类](http://docs.scala-lang.org/overviews/core/implicit-classes.html)将这些方法放在“数据”本身上。每种方法都是避免“静态”模式的方法,同时也避免了那些依赖关系。 (2认同)