如何Mock同一类中的方法?附同类方法Mock测试示例
这个问题在单元测试里真的挺常见的,我给你拆解几种靠谱的解决思路,咱们以常用的Mockito为例来说明:
方法一:用Mockito的Spy做部分Mock
这是最直接的方案,Spy的作用就是保留真实对象的大部分行为,只针对性地Mock你需要替换的方法。
具体步骤和代码示例:
import org.junit.Test; import org.mockito.Mockito; public class ATest { @Test public void testMethod2() { // 创建Spy对象,保留A类真实的方法逻辑,除了我们要Mock的method1 A aSpy = Mockito.spy(new A()); // 指定当method1传入10和20时,返回你想要的测试值(比如30) Mockito.when(aSpy.method1(10, 20)).thenReturn(30); // 调用要测试的核心方法method2 aSpy.method2(); // 还可以验证method1确实被按预期调用了 Mockito.verify(aSpy).method1(10, 20); } }
注意:这种方式只适用于method1是public/protected的情况,如果是private方法,Spy就搞不定了,得看后面的方案。
方法二:重构代码,拆分职责(推荐长期方案)
如果你的代码允许调整,这其实是更符合代码设计原则的做法——把method1的逻辑拆到独立的依赖类里,让A类的职责更单一,测试也会更简单。
比如这么改:
- 新建一个负责
method1逻辑的类:
public class Calculator { public int method1(int a, int b) { // 原来A类里method1的逻辑 return a + b; } }
- 在A类中通过构造方法注入这个新类的实例:
public class A { private Calculator calculator; // 构造注入,方便测试时替换成Mock对象 public A(Calculator calculator) { this.calculator = calculator; } public void method2() { int value = calculator.method1(10, 20); // 后续业务逻辑 } }
- 测试时直接Mock这个依赖类就行,完全不需要操心同一类方法的问题:
import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class ATest { @Mock private Calculator mockCalculator; @Test public void testMethod2() { MockitoAnnotations.openMocks(this); A a = new A(mockCalculator); Mockito.when(mockCalculator.method1(10, 20)).thenReturn(30); a.method2(); Mockito.verify(mockCalculator).method1(10, 20); } }
这种方式虽然要改代码,但长远来看代码的可维护性会提升很多,后续扩展也更方便。
方法三:用PowerMock处理私有方法(尽量别用,除非万不得已)
如果method1是private的,而且你完全没办法重构代码,那可以试试PowerMock——它能通过反射Mock私有方法,但缺点也很明显:会破坏Java的正常机制,测试代码的复杂度也会上升,所以优先考虑前两种方案。
JUnit4 + PowerMock的示例代码:
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(A.class) // 告诉PowerMock需要处理的目标类 public class ATest { @Test public void testMethod2() throws Exception { A a = PowerMockito.spy(new A()); // Mock私有方法method1,指定参数和返回值 PowerMockito.when(a, "method1", 10, 20).thenReturn(30); a.method2(); // 验证私有方法是否被正确调用 PowerMockito.verifyPrivate(a).invoke("method1", 10, 20); } }
总结一下:优先考虑重构拆分职责,其次用Spy做部分Mock,PowerMock尽量作为最后的备选方案。
内容的提问来源于stack exchange,提问作者abc123
相关产品推荐
相关产品推荐

