3

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.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Almost (but not quite) a duplicate of http://stackoverflow.com/questions/10092926/verifying-sequence-of-private-method-calls-in-unit-testing – Raedwald Mar 19 '14 at 13:39

4 Answers4

3

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();
    }
}
fge
  • 119,121
  • 33
  • 254
  • 329
  • Ok, I just tried with `spy()`, but it isn't working. What happens to the references in a class when we use spy? Are they null? Currently I was injecting some mock objects into it using @InjectMocks – Rohit Jain Mar 19 '14 at 13:49
  • What do you mean by "references in a class"? – fge Mar 19 '14 at 13:51
  • The `Child` class contains some other objects. Which I'm mocking and injecting. Will those be `null` when I use `@Spy`? – Rohit Jain Mar 19 '14 at 13:52
  • Cannot tell, really... I do "inject" mocks but by invoking constructors, and `spy()` works for me in that case as well. No idea for annotations, I don't use them, but I don't see why it would be any different... – fge Mar 19 '14 at 13:58
1

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.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • Actually that's not the real scenario. The `printParent()` method is actually inserting something into database. And the method is invoked based on some condition. I need to check if the method is invoked for that condition. Perhaps I'll update my question. – Rohit Jain Mar 19 '14 at 13:41
1

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

geoand
  • 60,071
  • 24
  • 172
  • 190
0

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.

Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90