I am using Mockito for some unit testing. I have the following classes:
public class Base {
public void say() {
System.out.println("Base"); // some work in the base class
}
}
public class Derived extends Base {
@Override
public void say() {
super.say(); // do the base class work
System.out.println("Derived"); // some additional work in the derived class
}
}
Now I want to test the Derived class's say() method while mocking the base say() method. I followed the suggestion here: Mockito How to mock only the call of a method of the superclass and I now have.
public class DerivedTest {
@Test
public void testSay() {
Derived obj = Mockito.spy(new Derived());
Mockito.doNothing().when((Base)obj).say();
obj.say();
// assert only "Derived" was output
}
}
But this doesn't work as it mocks both the base and the derived class implementation. I want to test just the extra logic in the derived class.
How can I do this.
Update: My solution
Since I couldn't change the base class as suggested, I modified my derived class to extract all the extra logic in a a separate method and just tested that method.
public class Derived extends Base {
@Override
public void say() {
super.say(); // do the base class work
doAdditionalWork(); // some additional work in the derived class
}
void doAdditionalWork() {
System.out.println("Derived");
}
}
public class DerivedTest {
@Test
public void testDoAdditionalWork() {
Derived obj = new Derived();
obj.doAdditionalWork();
// assert only "Derived" was output
}
}
This means that I am still not testing the derived say() method but given that the logic there is quite simple now, I hope I can be excused for this. The other downside is that I can't have a visibility stricter than package-private for the doAdditionalWork() method.
When you spy an object, you completely replace the implementation of the method(s) which you've defined a mock behavior for. So, as you noted in the question, this would not work.
One trick around this is to extract an additionalBehavior() method, and test it only, without spying or mocking:
public class Base {
public void say() {
System.out.println("Base"); // some work in the base class
additionalBehavior();
}
protected void additionalBehavior() {
// No implementation. Alternatively - make it abstract
}
}
public class Derived extends Base {
@Override
protected void additionalBehavior() {
System.out.println("Derived"); // some additional work in the derived class
}
}
public class DerivedTest {
@Test
public void testAdditionalBehavior() {
Derived obj = new Derived();
obj.additioanlBehavior();
// assert that "Derived" was the output
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With