Reputation: 3145
I'm writing a new class (Derived
), in TDD, using mockito and I have the following case:
Class Base:
public abstract class Base<T>{
//.......
protected final T baseCreate(T entity){
// implementation
}
}
Class Derived ( This is the class that I'm writing using TDD ):
public class Derived extends Base<MyObject> {
//.......
public MyObject create(MyObject entity){
baseCreate(entity); //This is what I want the implementation to be
}
}
When I came to write a test the will force me to invoke the baseCreate
method - I failed to understand how to do that.
Is there a way, using mockito, to verify that the create(...)
method in Derived
invokes the baseCreate(...)
method in the Base
class?
Thanks.
Upvotes: 4
Views: 297
Reputation: 79838
You say you're using TDD - so presumably, there's some specification of the required behaviour of either Derived
or Base
or both. So you'll write some tests around that specification. Those tests won't require you to make Derived
extend Base
- they'll simply require certain behaviour of each class; and it will be behaviour that you can implement without using inheritance at all.
Once your tests pass, then the next stage of TDD kicks in. This is the "refactor" stage, where you look for improvements in the way your classes are designed. This is the point at which you'll decide to make Derived
extend Base
, and make the create
method call baseCreate
. The wonderful thing is that when you do the refactor, you've already got some tests, to make sure that it has worked correctly.
Upvotes: 1
Reputation: 5971
Attila is right for most cases. What you want to test is that create actually does what you think it should do, not how it does it. The case you have here sounds like, "I already know that baseCreate does what I want it to do, so I don't want to re-test that, just that it gets called." This could be the case, but if so, then your superclass is really more of a collaborator. It's part of the reason to favor delegation over inheritance. Nonetheless, sometimes it is difficult to go back and change that design decision, so you have to test what you have.
You should still favor just checking that "create" does what you want it to do on the whole, but you might have a case where baseCreate is really doing a lot of stuff that requires a lot of set up of collaborators and such which makes it difficult and brittle to test. In that case, you would want to use a "spy". A spy wraps a "real" object and delegates to the real method calls unless you specifically create another expectation.
If you could make baseCreate public, you could use Mockito like this:
@RunWith(MockitoJUnitRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
public class YourTestCase {
@Spy
private Derived classUnderTest = new Derived();
@Test
public void privatePartialMockingWithPowerMock() {
MyObject myObject = new MyObject();
when(classUnderTest.baseCreate(myObject)).thenReturn(myObject);
// execute your test
classUnderTest.create(myObject);
verify(classUnderTest).baseCreate(myObject);
}
}
If you can't make baseCreate public, I think you could use PowerMock. It lets you verify private methods, but I don't think there would be any reason it couldn't do protected methods, too.
@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(Derived.class)
public class YourTestCase {
@Test
public void testCreate() {
Derived classUnderTest = PowerMockito.spy(new Derived());
MyObject myObject = new MyObject();
// use PowerMockito to set up your expectation
PowerMockito.doReturn(myObject).when(classUnderTest, "baseCreate", myObject);
// execute your test
classUnderTest.create(myObject);
// Use PowerMockito.verify() to verify result
PowerMockito.verifyPrivate(classUnderTest).invoke("baseCreate", myObject);
}
}
Upvotes: 4
Reputation: 28762
Unit tests are to test the behavior of the class, not its implementation. So you should not concern yourself with whther the Base
's baseCreate()
is called explicitly, rather wheter calling Derived
's cerate()
does exactly as you expect from an external observer's perspective
Upvotes: 5