如何在测试B类时Mock父类protected方法的super调用?
super.doSomething() Call in Subclass B for Testing Hey there, let's figure out how to skip testing the parent class A's doSomething() logic when you're testing subclass B. This is a common scenario when you want to focus solely on B's implementation without getting tangled up in A's code. Here are two reliable approaches:
Option 1: Mockito + Reflection (No Extra Libraries Needed)
Mockito doesn't natively support mocking parent class protected methods, but we can work around this with reflection to bypass access restrictions. Here's how:
- We'll use a Spy for B, which lets us keep B's own
doSomething()logic while stubbing out the parent's version. - Use reflection to make A's protected
doSomething()method accessible, then tell Mockito to do nothing when it's called.
Here's the code example:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import java.lang.reflect.Method; import static org.mockito.Mockito.doNothing; @RunWith(MockitoJUnitRunner.class) public class BTest { @Spy private B bInstance = new B(); @Test public void testDoSomethingWithoutSuperLogic() throws Exception { // Grab the protected doSomething method from parent class A Method parentDoSomething = A.class.getDeclaredMethod("doSomething"); parentDoSomething.setAccessible(true); // Stub the parent method to do nothing when called doNothing().when(bInstance, parentDoSomething).invoke(); // Call B's doSomething method bInstance.doSomething(); // Now you can run assertions on B's behavior without A's code interfering } }
Option 2: PowerMock (More Straightforward for Parent Class Mocks)
If you don't mind adding an extra library, PowerMock makes this way simpler by handling bytecode manipulation to intercept parent class calls.
First, add PowerMock dependencies matching your Mockito version (e.g., powermock-module-junit4 and powermock-api-mockito2). Then:
- Annotate your test class to use PowerMock's runner and prepare B for bytecode changes.
- Either suppress A's
doSomething()entirely or stub it with custom logic.
Example code:
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(B.class) // Required to modify B's bytecode public class BTest { @Test public void testDoSomethingWithSuperMocked() { B bInstance = new B(); // Option 1: Suppress A's doSomething so it doesn't run at all PowerMockito.suppress(PowerMockito.method(A.class, "doSomething")); // Option 2: Stub it with custom logic if needed // PowerMockito.doAnswer(invocation -> { // // Your mock behavior here (e.g., log something, return a value) // return null; // }).when(bInstance).doSomething(); // Execute B's method bInstance.doSomething(); // Assert your expectations for B's implementation } }
Quick Notes:
- For the Mockito+reflection approach, double-check the method signature (including parameters) if
doSomethingtakes arguments—you'll need to match them ingetDeclaredMethod. - PowerMock is great for complex scenarios, but it does add some overhead. Stick with Mockito+reflection if you want to keep your dependency list lean.
内容的提问来源于stack exchange,提问作者P.Zaw

