I have the following structure:
class Bar{
....
protected void restore(){
....
}
....
}
This class is extended by Foo
as below:
class Foo extends Bar{
....
@Override
public void restore(){ //valid override
super.restore();
....
}
}
In my jUnit test I would like to test that when foo.restore()
is called, the super.restore()
is called subsequently. Hence, below is my jUnit test method:
class FooTest{
@Tested
Foo _foo;
@Test
void testRestore(final Bar bar){
new Expectations(){{
bar.restore(); times = 1; // Error! bar.restore() not visible
}};
Deencapsulation.invoke(_foo,"restore");
}
}
Unfortunately, my test cannot compile. The reason is that 1) the restore()
of the parent is protected
and 2) FooTest
and Foo
exist together in a separate project (and therefore folder) vs. Bar
.
Is there anyway to achieve the desired test? I have checked the jMockit tutorials (many times over the past few months) and have not seen a similar test (same goes for a search on Google).
Update
With the help of the responses, I understand that enforcing subclasses to invoke super
is not the best practice, yet this is not my implementation and I still have to test it. I am still looking for a way to enforce my jUnit test to check if the call to the parent is taking place.
So basically you are trying to enforce a contract of calling the super and trying to allow for subclassing? I think that this is not easily done due to the dynamic dispatch that will hide the behavior in Java. I don't think that Mocking will catch this.
A way the ensure that the super is called would be to break out the super and the extension into 2 methods like
class Foo {
public final void restore() {
//parent code...
doRestore();
}
protected void doRestore() {
//empty base implementation
}
}
class Bar extends Foo {
protected void doRestore() {
//do my subclass specific restore stuff here
}
}
The following test should work:
public class FooTest
{
@Tested Foo _foo;
@Test
void restoreInFooCallsSuper(@Mocked final Bar bar)
{
new Expectations() {{
invoke(bar, "restore");
}};
_foo.restore();
}
}
The super.restore()
is supposed to do something useful no? some specific logic. In your test simply test that the outcome of invoking the super.restore()
happened.
Another way to look into it is the following. In the subclass before doing anything you implement an assert
that ensures that the super did its job correctly. This is a stronger check and is well known as part of Meyer's Design by Contract paradigm. In this context the subclass simply checks that the post-condition of the super.restore()
implementation holds before executing and by using assert
you know it will fail during Unit Tests but also during test integration runs of your application e.g.
class Foo extends Bar{
....
@Override
public void restore(){ //valid override
super.restore();
assert super_restore_worked_ok_condition : "restore post-condition failed";
....
}
}
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