Mockito模拟返回Future的Java方法:JUnit测试Mock失效排查
我来帮你排查下这个问题,这种Mock未被调用、返回结果还为null的情况,通常是几个常见的配置或Mock逻辑漏洞导致的,咱们一步步捋:
1. Mock对象没正确注入到被测试类里
首先得确认你有没有把globalUniqValidator和globalSubnetValidator这两个依赖正确Mock并注入到被测试类中:
- 你有没有用
@Mock注解标记这两个Validator? - 被测试类有没有用
@InjectMocks注解,让Mockito自动把Mock对象注入进去?
要是没做这一步,被测试类里用的还是真实的Validator实例,自然不会触发你Mock的Future逻辑,结果肯定是null。举个正确的配置例子:
@RunWith(MockitoJUnitRunner.class) public class YourServiceTest { // 要和被测试类里的依赖类型、变量名匹配 @Mock private GlobalUniqValidator globalUniqValidator; @Mock private GlobalSubnetValidator globalSubnetValidator; // 被测试的类,Mockito会自动把上面的Mock注入进来 @InjectMocks private YourTargetService underTest; }
2. Mock的方法调用匹配不精准
Mockito默认是严格匹配方法参数的,如果你Stubexecute()时用的参数和实际validate方法里调用的参数不一样,Mock就不会生效,返回默认值null。
比如你Stub的是:
when(globalUniqValidator.execute(anyString())).thenReturn(mockFuture);
但实际validate里调用的是execute(someCustomParamObject),那这个Stub就匹配不上,结果自然是null。
解决办法:
- 如果参数不重要,可以用
any()、any(YourParamType.class)这类匹配器放宽条件 - 要是参数必须精准匹配,就确保Stub时的参数和实际调用的完全一致
3. Future对象的Stub不完整
你是不是只Mock了Future对象,但没Stub它的get()方法?毕竟validate方法肯定会调用Future.get()来拿结果,如果你的Mock Future没Stub这个方法,要么抛出异常,要么返回null,导致你的uniqueResult/subnetResult为空。
正确的Stub姿势应该是这样:
// 先准备好要返回的Map结果 Map<ObjectId, Field> mockUniqueResultMap = new HashMap<>(); // 这里可以往map里加测试需要的内容 // Mock Future并Stub get()方法 Future<Map<ObjectId, Field>> mockUniqueFuture = Mockito.mock(Future.class); try { when(mockUniqueFuture.get()).thenReturn(mockUniqueResultMap); } catch (InterruptedException | ExecutionException e) { // 捕获异常,测试里不会触发 e.printStackTrace(); } // 把Mock Future绑定到Validator的execute方法上 when(globalUniqValidator.execute(any())).thenReturn(mockUniqueFuture);
4. Strict Stubbing模式下的未调用提示
Mockito 3+默认开启了Strict Stubbing模式,如果某个Mock对象的方法被Stub了但实际没被调用,就会提示“Mock未被使用”。这时候你要检查:
- 是不是你Stub了某个方法,但validate方法里根本没调用它?比如你Stub了
globalUniqValidator.execute(),但实际代码里没走这个分支? - 是不是Stub错了重载方法?比如
execute有多个重载版本,你Stub的是参数类型不同的那个?
5. 被测试类里直接new了Validator实例
如果你的validate方法里是通过new GlobalUniqValidator()这种方式创建的Validator,而不是通过依赖注入的方式引用成员变量,那Mockito根本无法Mock这个实例,自然不会调用你的Mock对象,结果就是null。比如这种错误写法:
public void validate() { // 这里new出来的对象,Mockito管不到 GlobalUniqValidator validator = new GlobalUniqValidator(); Future<Map<ObjectId, Field>> result = validator.execute(); }
这种情况得改成依赖注入,把Validator作为类的成员变量,通过构造方法或者Setter注入,这样Mockito才能替换成Mock对象。
内容的提问来源于stack exchange,提问作者user_531

