Rohit Jain
Rohit Jain

Reputation: 213223

Verify if inherited super class method was called from method being tested or not

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

Answers (4)

Nikos Paraskevopoulos
Nikos Paraskevopoulos

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

fge
fge

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

Raedwald
Raedwald

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

geoand
geoand

Reputation: 63991

I think you need to use a spy for Child instead of a mock.

Upvotes: 1

Related Questions