I'll show my problem using this example:
I have a class with a method foo
. That class has a subclass which overrides this method.
Subclass' method calls superclass' method. Can I verify that?
I don't want to test what foo
in superclass does. I just need to verify that it was called.
I know that refactoring could help (favour composition over inheritance, etc) but I am unable to do that.
Is there any way to achieve what I need?
Below is simple example of what I've tried
package tmp;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.times;
public class Example {
@Test
public void test() {
// given
ChildClass childClass = new ChildClass();
ChildClass spyChildClass = Mockito.spy(childClass);
// when
spyChildClass.foo(100);
// then
Mockito.verify((BaseClass) spyChildClass, times(1)).foo(101);
}
}
abstract class BaseClass {
public void foo(int n) {
System.out.printf("BaseClass.foo(%d)%n", n);
}
}
class ChildClass extends BaseClass {
@Override
public void foo(int n) {
System.out.printf("ChildClass.foo(%d)%n", n);
super.foo(n + 1);
}
}
And this is the result:
ChildClass.foo(100)
BaseClass.foo(101)
Argument(s) are different! Wanted:
childClass.foo(101);
-> at tmp.Example.test(Example.java:19)
Actual invocation has different arguments:
childClass.foo(100);
-> at tmp.Example.test(Example.java:16)
Expected :childClass.foo(101);
Actual :childClass.foo(100);
<Click to see difference>
Obviously it's not what I wanted to see.
I can't modify BaseClass
. I don't want to test BaseClass
(I am not responsible for it). I don't even neet to know what exactly it does. I just need to verify that its method was called. Wnything else is not my problem. Its the problem of people who maintain BaseClass
.
Test the behaviour of the class, not it's implementation.
Write the test such that the method is called and is expected to do something. Next check the object now represents what you now expect it to represent.
If BaseClass.foo
is expected to increment some counter by 100, yet Subclass.foo
increments some counter by 50 then calls the superclass, verify that the counter is now 150 and not just 50.
Don't peek the how - they may change over time. Do test the behaviour. The method foo
may do other things besides increase counters - check the state of the object not what it did.