本文详解为何 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)); // 可选:验证行为是否符合预期(如无异常、返回值等) }}
⚠️ 关键注意事项:
总结:Mockito 的“stubbing 失效”问题,90% 源于被测类未遵循依赖注入原则。重构 ServiceClass 为构造器注入后,mock 行为将严格生效,测试可控、可验证、可维护。