
本文详解为何 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 行为将严格生效,测试可控、可验证、可维护。











