Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock protected subclass method inherited from abstract class?

How to use Mockito or PowerMock to mock a protected method that is realized by a subclass, but inherited from an abstract super class?

In other words, I want to test "doSomething" method while mocking the "doSomethingElse".

Abstract super class

public abstract class TypeA {

    public void doSomething() {     

        // Calls for subclass behavior
        doSomethingElse();      
    }

    protected abstract String doSomethingElse();

}

Subclass implementation

public class TypeB extends TypeA {

    @Override
    protected String doSomethingElse() {
        return "this method needs to be mocked";
    }

}

Solution

Answers given here are correct and will work if classes involved are in the same package.

But if different packages are involved one option is to user PowerMock. The following example worked for me. Of course there might be other ways of doing it, this is one that works.

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ TypeB.class })
public class TestAbstract {

    @Test
    public void test_UsingPowerMock() throws Exception {
        // Spy a subclass using PowerMock
        TypeB b = PowerMockito.spy(new TypeB());
        String expected = "some value for mock";

        // Mock a method by its name using PowerMock again
        PowerMockito.doReturn(expected).when(b, "doSomethingElse");

        // Calls the 
        String actual = b.doSomething();
        assertEquals(expected, actual);     

    }
}

Note: Tests done using Java 5, jUnit 4.11, Mockito 1.9.0 and PowerMock 1.4.12.

like image 649
Evandro Pomatti Avatar asked Aug 18 '15 12:08

Evandro Pomatti


People also ask

Can protected methods be mocked?

Mocking Protected Methods How can you override the return of a protected method from your test? When testing a method with an underlying call to a protected method that you'd like to mock, one easy solution is to simply create a class extending the mocked class.

Can we declare protected method in abstract class?

Yes, you can declare an abstract method protected. If you do so you can access it from the classes in the same package or from its subclasses.

Can protected methods be inherited?

protected means access to the method is restricted to the same package or by inheritance. So the answer is, yes, protected methods can be overridden by a subclass in any package. By contrast, package (default) scoped methods are not visible even to subclasses that are in a different package.

Can protected methods be accessed by subclasses?

protected allows you access from the same package, or parent classes. protected allows access within the same package, or by subclasses. Neither is the case when using a superclass object reference.


1 Answers

You can use Mockito.CALLS_REAL_METHODS when mocking the abstract method. This will call the originals methods of the class and you can mock all abstract methods by yourself.

TypeA typeA = mock(TypeA.class, Mockito.CALLS_REAL_METHODS);
when(typeA.doSomethingElse()).thenReturn("Hello");
typeA.doSomething();

Or you test directly on the TypeB with a spy:

TypeB typeB = spy(new TypeB());
when(typeB.doSomethingElse()).thenReturn("Hello");
typeB.doSomething();
like image 157
mszalbach Avatar answered Oct 02 '22 15:10

mszalbach