Search code examples
javaunit-testingmockito

Stubbing a protected method of a base class


I'm using a third-party library, which has an abstract base class that the application code is supposed to extend. The subclass can then call a protected method on the base class as part of its processing. Whether that is good design or not can be discussed, but that's how it is. I want to test my subclass in isolation, and therefore stub the protected method of the base class.

I can create a Mockito spy for an instance of the subclass, and then stub out public methods of the ABC. However, this does not work for the protected one, since the following obviously is not permitted:

MySubclass obj = Mockito.spy(new MySubclass());
Mockito.when(obj.protectedMethod()).thenReturn(42); // error: protectedMethod() has protected access in AbstractBaseClass

Is there some other way of specifying a stub for that method?


Solution

  • Got it working by using the following:

    MySubclass obj = Mockito.spy(new MySubclass());
    
    Mockito.when(obj.publicMethod()).thenReturn(5);
    
    InvocationContainerImpl container = MockUtil.getInvocationContainer(obj);
    InvocationFactory invocationFactory = new DefaultInvocationFactory();
    Invocation invocation = invocationFactory.createInvocation(
        obj, new MockSettingsImpl<MySubclass>(),
        AbstractBaseClass.class.getDeclaredMethod("protectedMethod"), () -> null
    );
    container.resetInvocationForPotentialStubbing(new InvocationMatcher(invocation));
    container.addAnswer(i -> 4, Strictness.LENIENT);
    
    Assertions.assertEquals(9, obj.sum());
    

    It´s not very pretty, but when hidden behind a helper method, it´s not that bad. It uses classes from packages under org.mockito.internal, but they are documented as part of the public API.