Shanti Swarup Tunga
Shanti Swarup Tunga

Reputation: 641

Mocking a case class for testing

I have a case class

case class InputCriteria(a: Int) {
   val b: Int = config.getInt("some path")
}

How to mock this case class and override the value of b?

Upvotes: 0

Views: 1870

Answers (2)

Krzysztof Atłasik
Krzysztof Atłasik

Reputation: 22625

From scalamock faq:

Can I mock val / lazy val?

No, the Scala compiler will not allow overriding a val with a def, so with ScalaMock this is not possible. An option we are looking at for a possible future version of ScalaMock is scala.meta, but this is not yet available for all build targets we want. If you can, it is better to design a trait with a def and mock that instead. The concrete implementation can still override that def with a val to give invariant behaviour.

If you change your case class to trait you'd be able to override val with proxy.MockFactory.

If you changed you val to def you'd be able to override with plain mock.

You could also use the approach from Raman's answer, so unless you would want to make your class final it's working solution.

But what you should really do in my opinion is just creating trait:

trait InputCriteria {
     def b: Int
}

and then implementing it:

case class ConfigDrivenInputCriteria(config: Config) extends InputCriteria {
    override val b: Int = config.getInt("some path")
}

Then in test you could just reimplement it:

val testInputCritria = new InputCriteria {
    override def b: Int = 4
}

but it might be a little bit clunky if you've got a lot of fields in InputCriteria, but in that case you could also mock it:

val inputCriteria = stub[InputCriteria]
(inputCriteria.b _).when().returns(100)

Interface + implementation approach gives you the ability to test your code easily. You can also decide in implementing class if your properties should be defs, vals or lazy vals.

Upvotes: 5

Raman Mishra
Raman Mishra

Reputation: 2686

try this:

object abc extends App {
  case class A() {
    val x = 6
  }

  val a: A = new A() {
    override val x = 9
  }

  println(A().x, a.x)
}

Upvotes: 2

Related Questions