最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在不传入模拟对象的情况下利用Mockito模拟类内部创建的对象行为
时间:2026-06-17 08:18:57 编辑:袖梨 来源:一聚教程网
本文介绍一种符合 mockito 原则、无需 powermockito 或反射的轻量级方案:通过受保护的构造函数注入依赖,实现对类内部新建对象(如 client)的行为模拟,兼顾可测试性与代码整洁性。
本文介绍一种符合 mockito 原则、无需 powermockito 或反射的轻量级方案:通过受保护的构造函数注入依赖,实现对类内部新建对象(如 client)的行为模拟,兼顾可测试性与代码整洁性。
在单元测试中,当被测类(如 MyClass)自行实例化其依赖(例如通过 setupClient() 创建 Client 对象),而该依赖并未通过构造函数或 setter 注入时,直接用 Mockito 模拟其行为会受限——因为 Mockito 无法拦截私有方法调用或控制内部对象生命周期。但强行使用 PowerMockito 或修改类结构(如添加 @PrepareForTest)不仅增加复杂度,还违背“测试友好设计”的初衷。
推荐实践:引入受保护的构造函数(Protected Constructor)
这不是破坏封装,而是为测试提供一条合法、低侵入的扩展路径。核心思想是:保留原有无参构造函数供生产环境使用,同时新增一个带依赖参数的 protected 构造函数,仅用于测试场景:
public class MyClass { private final Client someClient; // 生产环境使用的默认构造函数 public MyClass() { this.someClient = setupClient(); } // 仅用于测试的受保护构造函数(不暴露给外部模块) protected MyClass(Client client) { this.someClient = Objects.requireNonNull(client, "Client must not be null"); } private Client setupClient() { // 实际初始化逻辑,如 new OkHttpClient() 或配置连接池等 return new DefaultClient(); } public void methodIWantToTest(String requestString) { this.someClient.makeApiCall(requestString); // 其他业务逻辑 }}
在测试类中,直接使用该受保护构造函数传入 Mock 对象:
public class MyClassTest { private MyClass SUT; private Client mockClient; @BeforeEach void setUp() { mockClient = Mockito.mock(Client.class); SUT = new MyClass(mockClient); // ✅ 使用受保护构造函数 } @Test void testMethodIWantToTest() { // 配置模拟行为 Mockito.when(mockClient.makeApiCall(Mockito.anyString())) .thenReturn(Response.success("mocked response")); // 执行被测方法 SUT.methodIWantToTest("GET /api/users"); // 验证交互 Mockito.verify(mockClient).makeApiCall("GET /api/users"); Mockito.verifyNoMoreInteractions(mockClient); }}
✅ 优势说明:
- 完全兼容标准 Mockito,无需额外依赖(如 PowerMockito);
- 不违反面向对象原则,protected 修饰符确保测试专用入口不被误用;
- 保持类职责清晰:构造逻辑仍由类自身管理,仅开放可控的测试钩子;
- 易于演进:未来若采用 Spring 等 DI 框架,可自然升级为 @Autowired 构造注入。
⚠️ 注意事项:
- 避免将 protected 构造函数声明为 public,防止被非测试代码滥用;
- 若 Client 是 final 类或方法不可 mock(如 JDK 内置类),需配合 mockito-inline(Mockito 3.4.0+)启用字节码增强;
- setupClient() 中若含副作用(如网络/IO 初始化),务必确保其在测试中被完全绕过——这正是本方案的价值所在。
总结:可测试性不是测试框架的义务,而是设计的责任。通过微小的构造函数重构,即可在零反射、零第三方工具的前提下,让私有依赖变得“可替换、可验证、可预测”,这才是 Mockito 倡导的正向测试实践。
相关文章
- 望月线下测试资格如何获取 望月线下测试资格获取方式 07-31
- 崩坏星穹铁道4.3更新了哪些 崩铁4.3版本更新公告 07-31
- 金铲铲之战5月29日更新公告 金铲铲之战17.4版本更新全部内容 07-31
- 和平精英全职高手皮肤价格多少 和平精英全职高手皮肤获取攻略 07-31
- 迷雾大陆官网入口在哪-官方地址及下载渠道一览 07-31
- 三国志战略版于吉更新分享 三国志战略版于吉更新内容解读 07-31