19

I have three very simple classes. One of them extends parent class.

public class Parent{
    protected String print() {
        // some code
    }
}

Here is a child class.

public class Child extends Parent {
    /**
     * Shouldn't invoke protected Parent.print() of parent class.
     */
    @Override
    protected String print() {
        // some additional behavior
        return super.print();
    }
}

And test class.

public class ChildTest {

    @Test
    public void should_mock_invocation_of_protected_method_of_parent_class() throws Exception {

        // Given
        Child child = PowerMockito.mock(Child.class);
        Method method = PowerMockito.method(Parent.class, "print");
        PowerMockito.when(child, method).withNoArguments().thenReturn("abc");

        // When
        String retrieved = child.print();

        // Than
        Mockito.verify(child, times(1)).print(); // verification of child method
        Assert.assertEquals(retrieved, "abc");
    }
}

I need to verify super.print() invocation. How can I do it?

Aaron
  • 1,294
  • 4
  • 14
  • 27
  • This doesn't make sense to me, if you need to verify super.print() invocation, it is verified by verifying child method .print() invocation. It is calling the super class print() to return the result. Alternatively, just test the parent. – Mauno Vähä Jul 22 '14 at 21:02
  • The test passes, no matter if you call `super.print()` in child or not. It appears Mockito cannot handle this situation: see [Powermock - mocking a super method invocation](http://stackoverflow.com/questions/14125774/powermock-mocking-a-super-method-invocation) – zardosht Jul 22 '14 at 21:26

3 Answers3

4

This is a long time ago question, but here is how i did it, using Mockito spy, create a method which call the parent method in the child class:

public class Child extends Parent {
    /**
     * Shouldn't invoke protected Parent.print() of parent class.
     */
    @Override
    protected String print() {
        // some additional behavior
    return callParent();
    }

    protected callParent()
    {
      super.print();
    }

}

And in the test :

@Test
public void sould_mock_invocation_of_protected_method_of_parent_class() throws Exception {

    // Given
    Child child = Mockito.spy(new Child());
    Mockito.doReturn(null)
           .when(child)
           .callParent();
    // When
    String retrieved = child.print();

    // Then
    Mockito.verify(child, times(1)).callParent(); // verification of child method
    Assert.assertEquals(retrieved, "abc");
}

Note: this test only check we call the parent method in the child class

dephinera
  • 3,703
  • 11
  • 41
  • 75
Geof
  • 65
  • 1
  • 2
0

This can be solved by applying "composition over inheritance" pattern.

public class QuasiChild {

    private final QuasiParent quasiParent;
 
    public QuasiChild(QuasiParent quasiParent) {
        this.quasiParent = quasiParent;
    }
    
    public void someMethod() {
        // do something...

        quasiParent.someMethod();
    }
} 

Now you can mock and verify QuasiParent#doSomeMethod() invocation.

matoni
  • 2,479
  • 21
  • 39
-4

If you call super.print() in the Child class' print() method, of course the Parent class implementation of print() will be called. How to verify that it actually happens depends on what the Parent class implementation actually does.

P.S. the comments in your code Shouldn't invoke protected Parent.print() of parent class and Parent.print() method shouldn't be invoked. are wrong.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • I need to verify that the method `Parent.print()` was invoked. But at the same time I want to mock it (I don't want to invoke real `Parent.method()`). – Aaron Jul 22 '14 at 19:59
  • 1
    @Aaron Then print something in that method, and verify that it gets printed. – Eran Jul 22 '14 at 20:00
  • @Aaron Perhaps I'm failing to understand what you are trying to do. I'm not familiar with Mockito. – Eran Jul 22 '14 at 20:02
  • Actually I want to mock Parent method. But at the same time I want to verify the this method was invoked. And of cause I don't need to execute logic of parent method (it calls "to make a mock of method"). – Aaron Jul 22 '14 at 20:05