user811602
user811602

Reputation: 1354

Unit test: mock nested scala val

I have two case class A and AHelper

case class AHelper(data: String) {
  def getData() = {...} // Complex operation inside
}

case class A(data1: String, data2: String) {
  private val aHelper = AHelper(data2)    // AHelper instance
  def getData() = {data1 + aHelper.getData; ...} // Complex operation inside
}

class A has instance of AHelper as one of its member.

I want to write unit tests for A only, mocking AHelper

Scala version: 2.11

Upvotes: 0

Views: 870

Answers (1)

Dima
Dima

Reputation: 40500

The helper should be a parameter:

case class A(data1: String, data2: String)(aHelper: AHelper = AHelper(data2))

Now in your tests, you can do: A("foo", "bar")(mock[AHelper])

If you don't like the second parameter list, there are a few options:

Make it implicit:

case class A(data1: String, data2: String)(implicit aHelper: AHelper = AHelper(data2))

This lets you create instances with just new A("foo", "bar") without having to tuck the () on the end

Or, create a companion object:

 object A {
   def apply(data1: String, data2: String): A = A(data1, data2)(AHelper(data2))
 }

Note also, that case classes with involved logic that require unit tests are ... unusual. Case class is meant to be just a dumb holder of the data, a tuple with named fields if you will. You should consider either splitting your logic out of these classes, or making them "regular" (non-case) classes instead.

For example:

case class A1(data: String)
case class A2(data1: String, data2: A1)

trait AHelper {
  def getData(a1: A1)
}

class  AReader(helper: AHelper) {
  def getData(a: A2) = a.data1 + helper.getData(a.data2))
}

Now, there are no questions how to properly test this, right?

Upvotes: 4

Related Questions