Farah
Farah

Reputation: 2621

How to mock a val initialized by a function in an object in Scala?

I have an object in Scala like follows

object Foo {

  val launchDate = LocalDate.now()
  ...
}

I need to do a Unit Test in which I replace lauchDate by a given date, Ex: 25 June 2001. Is there a way to mock launchDate? Which framework would you recommand me?

Thank you

Upvotes: 1

Views: 3166

Answers (3)

Joe K
Joe K

Reputation: 18424

I'll cut against the grain here a bit and say that dates/times/clocks are one of the canonical examples of something you should be doing with "dependency injection". I use quotes since I think just passing it as a constructor arg is fine rather than all of those fancy frameworks.

I tend to think this sort of mocking should be a bit of a last resort. I would rather do:

class Foo(clock: { def now(): LocalDate }) {
  val launchDate = clock.now()
  // ... rest of Foo's original implementation ...
}

object FooRealtime extends Foo(LocalDate) {
} // previous users of Foo can just use FooRealtime

Then in tests you can pass in a different implementation that returns whatever dates you want.

Upvotes: 3

Duelist
Duelist

Reputation: 1572

I've heard that ScalaMock supported the feature of mocking singleton objects with method mockObject. But it was removed from ScalaMock 3.

But if you had a trait instead of object you could use ScalaMock 4 with ScalaTest, namely using proxy.MockFactory:

import java.time.LocalDate

import org.scalamock.scalatest.proxy.MockFactory
import org.scalatest.FunSuite

class FooTest extends FunSuite with MockFactory {
  test("it should return local date") {
    val launchDate: LocalDate = LocalDate.of(2017, 6, 15)
    val m = mock[FooService]
    m.expects('launchDate)().returning(launchDate)
    assertResult(launchDate)(m.launchDate)
  }
}

build.sbt dependencies:

libraryDependencies ++= Seq("org.scalactic" %% "scalactic" % "3.0.5",
                            "org.scalatest" %% "scalatest" % "3.0.5" % Test,
                            "org.scalamock" %% "scalamock" % "4.1.0" % Test)

Upvotes: 0

Dennis Hunziker
Dennis Hunziker

Reputation: 1293

org.mockito.internal.util.reflection.Whitebox seems to work just fine. Since you tagged the question with mockito I assume you already have that on your classpath anyway.

Whitebox.setInternalState(Foo, launchDate, <your date>)

Upvotes: 2

Related Questions