Android Kotlin中使用Mockito测试带Lambda回调的函数
解决Mockito测试Lambda回调的编译失败与流程保留问题
嘿,这个问题我之前也碰到过——当Mock的方法带有Lambda回调参数时,直接Mock的话回调不会被执行,导致原代码里依赖回调的逻辑走不下去,甚至编译报错。别担心,用Mockito的doAnswer就能完美解决,既保留原代码流程,又能自定义回调的返回值,还能验证后续的方法调用。
首先先明确下我们要测试的类结构(假设你的代码大致是这样):
// 待测试的类 public class MyClass { private final MyStore myStore; private final ObjectX objectX; public MyClass(MyStore myStore, ObjectX objectX) { this.myStore = myStore; this.objectX = objectX; } public void doClassAction() { // 调用MyStore的方法,传入Int参数和String类型的Lambda回调 myStore.doStoreAction(100, callbackResult -> { // 原代码逻辑:拿到回调结果后调用objectX的方法 objectX.doObjectAction(callbackResult); }); } } // 被Mock的依赖类 public interface MyStore { void doStoreAction(int param, StringCallback callback); } // Lambda对应的函数式接口 @FunctionalInterface public interface StringCallback { void onResult(String result); } // 需要验证调用的依赖类 public class ObjectX { public void doObjectAction(String input) { // 业务逻辑 } }
接下来是核心的测试代码,用doAnswer处理回调:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) public class MyClassTest { // Mock两个依赖对象 @Mock private MyStore myStore; @Mock private ObjectX objectX; // 把Mock的依赖注入到待测试的MyClass实例中 @InjectMocks private MyClass myClassUnderTest; @Test public void doClassAction_ShouldTriggerObjectXMethodWithCustomCallbackValue() { // 第一步:定义我们想要传给回调的自定义返回值 String customCallbackResult = "mock_success_result"; // 第二步:拦截MyStore的doStoreAction调用,手动执行回调 doAnswer(invocation -> { // 获取方法的第二个参数(索引从0开始)——也就是我们的Lambda回调 StringCallback callback = invocation.getArgument(1); // 执行回调,传入我们自定义的返回值,让原代码的Lambda逻辑继续走下去 callback.onResult(customCallbackResult); return null; // 因为doStoreAction是void方法,返回null即可 }).when(myStore).doStoreAction(anyInt(), any(StringCallback.class)); // 第三步:执行待测试的方法 myClassUnderTest.doClassAction(); // 第四步:验证objectX的doObjectAction是否被正确调用,参数是我们自定义的回调值 verify(objectX, times(1)).doObjectAction(customCallbackResult); } }
关键知识点解释:
doAnswer的作用:它允许我们拦截Mock对象的方法调用,自定义方法的执行逻辑——这里我们就是用它来获取并执行传入的Lambda回调,解决了Mock对象不会自动处理回调的问题。- 获取回调参数:通过
invocation.getArgument(index)可以拿到方法调用时传入的参数,这里第二个参数就是我们的StringCallbackLambda。 - 保留原流程:手动执行
callback.onResult()后,原代码里Lambda内部的逻辑(调用objectX.doObjectAction)会正常执行,完全保留了业务流程。 - 验证方法调用:最后用
verify确认objectX的方法是否被调用了一次,且参数符合我们的预期,确保逻辑正确性。
注意事项:
- 确保你使用的是Mockito 2.x及以上版本,它对Java 8的函数式接口支持更好,
any(StringCallback.class)能正确匹配Lambda参数。 - 如果
doStoreAction是有返回值的方法,doAnswer里的return要对应返回类型,比如返回String的话就return "mock_return"。 - 如果你想测试不同的回调场景(比如失败场景),只需要修改
customCallbackResult的值即可,非常灵活。
内容的提问来源于stack exchange,提问作者kioli
相关产品推荐
相关产品推荐

