Reputation: 213223
Ok so I'm stuck with Mockito again. Here's the situation:
I've a super class, and a subclass:
class Parent {
protected void insertData() {
// Here is some database related stuff
someObject.storeData();
}
}
class Child extends Parent {
private String name;
public void printHierarchy(int x) {
if (x > 1) {
insertData()
} else {
System.out.println("Child");
}
}
}
And in my unit test class, I'm testing Child
class printHierarchy()
method:
@RunWith(SpringJUnit4ClassRunner.class)
public class ChildTest {
@InjectMocks // To inject mock objects
private Child child = new Child();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// This is where the issue is
doNothing().when(child).insertData();
}
@Test
public void testPrintHierarchy() {
child.printHierarchy(5);
// Here also
verify(child, times(1)).insertData();
}
}
So the issue is, how do I verify if insertData()
method was called from Child#printHierachy()
?
When I try the above code, I get the error as:
Argument passed to when() is not a mock!
Of course, child
is not a mock. I'm testing that class. But how do I resolve this issue?
No I haven't found any duplicate of this. One question was pretty similar though, but it didn't help me.
Upvotes: 3
Views: 4926
Reputation: 40296
I think the mistake may be conceptual. If Child
extends Parent
, then the methods of Parent
are part of the implementation, i.e. the System Under Test.
If the Parent
needs to be mocked independently of the Child
, then maybe you should use composition instead of inheritance:
public class Child {
private Parent parent;
public void printHierarchy() {
parent.printParent();
}
// setters/getters
}
Now the Parent
is mockable and you can test whether printParent()
was called or not.
If the class hierarchy is conceptually correct, then you should not need to test internal implementation details (i.e. that the interface/public method calls some other). You do not care about implementation details.
Upvotes: 0
Reputation: 121712
You need to use spy()
for that. The following code works:
public final class Bin
{
@Test
public void spyMe()
{
final Child c = spy(new Child());
doNothing().when(c).printParent();
c.printHierarchy(1);
verify(c).printParent();
}
}
class Parent {
protected void printParent() { System.exit(0);}
}
class Child extends Parent {
private String name;
public void printHierarchy(int i) {
if (i > 0)
printParent();
}
}
Upvotes: 3
Reputation: 48644
Whether method printHierachy()
calls method printParent()
is surely an implementation detail of method printHierachy()
, and so should not be tested for. Unit tests should check that a method has the required outputs.
For printing methods, checking the format of the printed output would do. For a method that updates a data-base, check that the data-base contains the expected values. For a method that manipulates a domain-model object in a specified manner, check that the domain object is in the correct state. And so on.
Upvotes: 1