Search code examples
scalascalatest

PrivateMethodTester and Inheritance


So I have a class:

class MyParent {
    private def myMethod() = 12
}

And a class:

class MyChild extends MyParent {
}

In my test I want to do:

val c = new MyChild()

val m = PrivateMethod[MyChild]('myMethod)
assertEquals(12, c invokePrivate m())

But I get:

java.lang.IllegalArgumentException: Can't find a private method named: myMethod

Any idea how to test the method defined in the parent using the child class ?

My use case is obviously more complex, so testing the parent method is different than testing the child method.

Thank you.

Edit:

One solution I found is to change MyParent#myMethod to protected and then have in the child:

private def wrapMyMethod() = super.myMethod()

Solution

  • This is not related to scalatest:

    The fact that def myMethod() = 12 is private in the base class means it can't be used from the child classes.

    The compiler won't be able to perform new MyChild().myMethod() nor will the PrivateMethodTester be able to invoke it via introspection.


    Unrelated to the error: the type parameter of PrivateMethod should be Int (the return type of the method being tested) and not MyChild:

    You can test it on the base class:

    val m = PrivateMethod[Int]('myMethod)
    new MyParent() invokePrivate m()
    

    insteadd of:

    val m = PrivateMethod[MyParent]('myMethod)
    new MyParent() invokePrivate m()
    

    If def myMethod() = 12 was made protected then you wouldn't need to create a wrapper in the child class with the only intent to test it (as a base rule, I think unit testing should never impact the actual code), you could directly test the protected method from the base class.

    To test a protected method, you can create a new class in your test class which extends the class containing the protected method and indeed wraps it in a public method:

    class MyParentMock extends MyParent {
      def wrapMyMethod() = myMethod()
    }
    
    test("my_test") {
      assertEquals(12, new MyParentMock().wrapMyMethod())
    }