最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何正确使用 Mockito 进行依赖注入式单元测试:避免真实方法调用
时间:2026-07-09 10:03:58 编辑:袖梨 来源:一聚教程网
本文详解为何 Mockito 未生效的根本原因:被测类 ServiceClass 在方法内自行 new 实例,导致 @Mock 注入失效;并提供基于构造器注入的完整解决方案,确保 mock 行为真正生效。
本文详解为何 mockito 未生效的根本原因:被测类 `serviceclass` 在方法内自行 `new` 实例,导致 `@mock` 注入失效;并提供基于构造器注入的完整解决方案,确保 mock 行为真正生效。
在使用 Mockito 进行单元测试时,一个常见却极易被忽视的错误是:被测类内部直接 new 出依赖对象,而非通过依赖注入获取。这会导致即使你正确声明了 @Mock 和 @InjectMocks,Mockito 也无法接管该依赖——因为运行时实际调用的是全新创建的真实对象,而非你准备的 mock 实例。
回顾你的代码片段:
// ❌ 错误:ServiceClass 内部手动 new,绕过所有依赖注入public void sendPayload(final ValidRequest req) { EncSercice encService = new EncSercice(); // ← 真实实例!mock 被完全忽略 String str = encService.callFn(req, keys);}
此时,@Mock EncSercice encService 和 @InjectMocks ServiceClass service 完全无效——service 对象虽被创建,但其内部逻辑始终使用新 new 的 EncSercice,因此你看到 callFn 的日志输出,且 Mockito.verify() 永远失败。
✅ 正确做法是:将依赖作为构造参数传入,使 ServiceClass 成为可测试的、依赖明确的组件:
// ✅ 正确:ServiceClass 通过构造器接收依赖(推荐)public class ServiceClass { private final EncSercice encService; public ServiceClass(EncSercice encService) { this.encService = Objects.requireNonNull(encService, "encService must not be null"); } public void sendPayload(final ValidRequest req) { // ... 其他逻辑 String str = encService.callFn(req, keys); // ← 调用的是注入的 mock 实例 }}
对应地,测试类需同步更新(使用现代 JUnit 5 + Mockito 4+ 推荐写法):
import org.junit.jupiter.api.BeforeEach;import org.junit.jupiter.api.Test;import org.mockito.Mock;import org.mockito.MockitoAnnotations;import static org.mockito.Mockito.*;class ServiceClassTest { @Mock private EncSercice encService; private ServiceClass service; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); // 替代已废弃的 initMocks() service = new ServiceClass(encService); // 显式构造,确保 mock 被注入 } @Test void testEncryptRegisterTransactionPayload() { // Given ValidRequest request = new ValidRequest(); String stubbedResult = "Stubbed encrypted message"; when(encService.callFn(anyString(), any(String[].class))) .thenReturn(stubbedResult); // When service.sendPayload(request); // Then verify(encService).callFn(anyString(), any(String[].class)); // 可选:验证行为是否符合预期(如无异常、返回值等) }}
⚠️ 关键注意事项:
- 禁止在被测类中 new 依赖对象:这是破坏可测试性的根本原因;
- 优先使用构造器注入:比字段注入更清晰、更易测试、更符合不可变性原则;
- @InjectMocks 仅对字段注入有效,且依赖于反射匹配,不推荐用于复杂场景;显式构造(如 new ServiceClass(mock))更可靠、更易调试;
- 确保 EncSercice 类非 final(否则 Mockito 默认无法 mock),若必须为 final,需启用 mockito-inline 并配置 mock-maker-inline;
- 使用 anyString() 和 any(String[].class) 匹配参数时,注意类型一致性(String[].class 是正确的 Class 字面量)。
总结:Mockito 的“stubbing 失效”问题,90% 源于被测类未遵循依赖注入原则。重构 ServiceClass 为构造器注入后,mock 行为将严格生效,测试可控、可验证、可维护。
相关文章
- 努比亚z50spro有无线充电吗 07-09
- 圆形水花飞溅动感摄影 07-09
- 地铁站台电影肖像 07-09
- 野花丛电影感人像 07-09
- 科幻风咖啡机 Boss 战 07-09
- 超现实微距时尚创作室 07-09