Crazy Ninja Crazy Ninja - 4 months ago 77
Java Question

Mock inherited method in Mockito Java

My class structure is as follows:

public class MyParentClass {

void doSomethingParent(){
System.out.println("something in parent");
}
}

public class MyClass extends MyParentClass{


protected String createDummyRequest(Holder myHolder){
//...
super.doSomethingParent();//I want to avoid this
//...
callingDB();
return "processedOutput";
}

private void callingDB(){
System.out.println("Calling to DB");
}
}


Then my unit test:

public class UnitTest {


public void testCreateDummyRequest(){
//create my mock holder
Holder mockHolder = new Holder();

MyClass mockObj = Mockito.mock(MyClass.class);
//mock doSomethingParent()
//mock callingDB()

//as mockObj is a fully mock, but I need to run my real method
//Mockito.when(mockObj.createDummyRequest(mockHolder)).thenCallRealMethod();
mockObj.createDummyRequest(mockHolder);
//Problem: doSomethingParent() is getting called though I have mocked it
}
}


How do I prevent the calling of the super.doSomethingParent() in my method? (method which I am writing my test)

Answer

With this class structure mocking and testing is real hard. If possible, I'd advice to change the structure as in mist cases a class structure that's hard to mock and test is equally hard to extend and maintain.

So if you could change your class structure to something similar to:

public class MyClass {

    private DoSomethingProvider doSomethingProvider;

    private DbConnector dbConnector;

    public MyClass (DoSomethingProvider p, DbConnector c) {
        doSomethingProvicer = p;
        dbConnector = c;
    }


    protected String createDummyRequest(Holder myHolder){
        //...
        doSomethingProvider.doSomethingParent();
        //...
        dbConnector.callingDB();
        return "processedOutput";
    }
}

Then you could easily create your instance with mocks of DoSomethingProvider and DbConnector and voila....

If you can't change your class structure you need to use Mockito.spy instead of Mockito.mock to stub specific method calls but use the real object.

public void testCreateDummyRequest(){
    //create my mock holder
    Holder mockHolder = new Holder();

    MyClass mockObj = Mockito.spy(new MyClass());

    Mockito.doNothing().when(mockObj).doSomething();

    mockObj.createDummyRequest(mockHolder);
}

Note: Using the super keyword prevents Mockito from stubbing that method call. I don't know if there is a way to stub calls to super. If possible (as in you didn't override the parent method in your class), just ommit the keyword.

Comments