Scala:模拟一个封闭的对象

Scala: Mocking an enclosed object

我正在尝试为对象 A 编写单元测试,它使用了另一个对象 B 的一些方法。如何覆盖 B 的方法?

A.scala

import somePackage.B

object A { // This is to be tested
def fun1(str: String) = {
   val str2 = processStr(str) //Say str2 = "sahil"
   B.doSomething(str2)  // This is to be overridden
}

B.scala

object B {
  private def doSomething(str: String) = {
   // do something
    "abc"
  }
}

ATest.scala

class ATest extends FlatSpec {
    it "should return sahil instead of abc" in {
        // Do something to override B.doSomething
        A.fun1("someString") 
    }
}

没有简单的方法可以做到这一点。在不使用 DI 的情况下,我唯一想到的就是使用 package-private 修饰符重载 fun1:

package somePackage
import somePackage.B

object A {

  def fun1(str: String) = fun1(B.doSomething)

  private[somePackage] def fun1(str: String, f: (String) => String) = {
    val str2 = processStr(str)
    f(str2)
  }

}

然后你可以将任何你想要的模拟传递给 fun1

这是架构层面的设计失败,是典型的XY problem。如果没有(真正的)令人信服的理由,您不应该使用 单例

而不是为了可测试性和模块化,考虑显式注入你的依赖(现在你正在声明 AB 之间的依赖 隐式 通过单例).

class A(b: B) {
  def fun1(str: String) = b.doSomething(str)
}

class B {
  def doSomething(str: String) = "abc"
}

class ATest extends FlatSpec {
  it "" in {
    val b = new B { override def doSomething(str: String) = "testing..." }
    val a = new A(b)
    a.fun1("someString") must beEqual "testing..."
  }
}