16

I want to mock an inherited protected method. I can't call this method directly from java code as it is inherited from class that in another package. I can't find a way to specify this method to stub in in when(...)

package a;

public class A() {
    protected int m() {}
}

package b;

public class B extends a.A {
    // this class currently does not override m method from a.A
    public asd() {}
}

// test
package b;

class BTest {
    @Test
    public void testClass() {
        B instance = PowerMockito.spy(new B());
        PowerMockito.when(instance, <specify a method m>).thenReturn(123);
        //PowerMockito.when(instance.m()).thenReturn(123); -- obviously does not work
    }
}

I looked at PowerMockito.when overrides and this seems that they are all for private methods only!

How to specify protected method?

Felipe Pereira
  • 1,008
  • 11
  • 24
michael nesterenko
  • 13,240
  • 23
  • 104
  • 175
  • @AndroidKiller, updated code with class name. Actually they could be from Mockito, but I use powermock and these methods has the same meaning there – michael nesterenko Nov 29 '11 at 14:32
  • That's of the reason why we should always prefer composition over inheritance. If you can't just redefine this method in your tested code, just like you'll do with legacy code. – Brice Nov 29 '11 at 14:49

1 Answers1

26

Nutshell: Can't always use when to stub spies; use doReturn.

Assuming static imports of spy and doReturn (both PowerMockito):

@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)
public class BTest {
    @Test public void testClass() throws Exception {
        B b = spy(new B());
        doReturn(42).when(b, "m");
        b.asd();
    }
}

You could also @PrepareForTest(A.class) and set up the doReturn on when(a, "m"). Which makes more sense depends on the actual test.

Dave Newton
  • 152,765
  • 23
  • 240
  • 286
  • wow, thank you. Interestingly when I tried to use Method instance instead of method string name stubbing failed with exception message about wrong number of arguments. But with string name all works perfectly. – michael nesterenko Nov 29 '11 at 14:50
  • @mishanesterenko Yep, it can get a little convoluted sometimes. Another option is always subclassing `B` for the purposes of the test. Not always an option, but less "magical" than modifying bytecode ;) – Dave Newton Nov 29 '11 at 14:52
  • What would you do if you have set Methode returning void. Let's say `m` is a set-Methode like void m(MySpecialParser parser). This parser is used to parse my text. How can i mock it? – Kayser Sep 19 '12 at 08:52
  • @Kayser Isn't there a doNothing? I don't recall off the top of my head. – Dave Newton Sep 19 '12 at 12:13
  • Good answer. FWIW: It pretty much follows the convention from [PowerMock's doc](https://code.google.com/p/powermock/wiki/MockitoUsage13) (the "A full example of partial mocking of a private method" section applies to protected too). – cellepo Apr 25 '14 at 16:21