How can a private class method be tested in Scala?

I have a companion object with a private method, like so:

package com.example.people

class Person(val age: Int)

object Person {
  private def transform(p: Person): Person = new Person(p.age + 1)
}

I would like to test this method, with something like:

class PersonSpec extends FlatSpec {

  "A Person" should "transform correctly" in {
    val p1 = new Person(1)
    val p2 = Person.transform(p1) // doesn't compile, because transform is private!
    assert( p2 === new Person(2) )
  }

}

Any help on having test code access private methods?

Actually, as it is written, I might be able to create a subclass of Person, but what if Person is declared as final or sealed?

Thanks!


Solution 1:

I am in the middle when it comes to testing everything. I don't usually test everything, but sometimes it's really useful to be able to unit test a private function without having to mangle my code to make it possible. If you're using ScalaTest, you can use the PrivateMethodTester to do it.

import org.scalatest.{ FlatSpec, PrivateMethodTester }

class PersonSpec extends FlatSpec with PrivateMethodTester {

  "A Person" should "transform correctly" in {
      val p1 = new Person(1)
      val transform = PrivateMethod[Person]('transform)
      // We need to prepend the object before invokePrivate to ensure
      // the compiler can find the method with reflection
      assert(p2 === p1 invokePrivate transform(p1))
    }
  }

That may not be exactly what you want to do, but you get the idea.

Solution 2:

You could declare your method to be package private:

private[people] def transform(p: Person): Person = new Person(p.age + 1)

If you put PersonSpec in the same package it will be able to access it.

I leave it to you to decide if it's really wise to unit test a private method :)