0

I'm trying to write a unit test for object A, which uses some methods from another object B. How do I override B's methods?

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") 
    }
}
Sahil Sareen
  • 1,813
  • 3
  • 25
  • 40

2 Answers2

2

This is a design failure at architectural level and a typical XY problem. You should not use singleton without a (really) compelling reason.

Instead for both testability and modularity, consider injecting your dependency explicitly (right now you are declaring the dependency between A and B implicitly through singleton).

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..."
  }
}
Community
  • 1
  • 1
Daniel Shin
  • 5,086
  • 2
  • 30
  • 53
0

There is no easy way to do this. Without using DI the only thing that comes to my mind is to overload fun1 with package-private modifier:

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)
  }

}

Then you can pass any mock you would like into fun1

freakybit
  • 59
  • 5