You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用Mockito验证RxJava 2中Observable的实际执行逻辑?

如何用Mockito验证RxJava Observable/Completable的实际执行

你碰到的这个问题其实很典型——Mockito默认只能验证方法是否被调用,但没法直接验证RxJava流里的逻辑是否真的被执行了。咱们先拆解下问题根源,再给出解决方案。

问题根源分析

你当前的测试里,verify(bar, times(1)).method3()通过了,是因为andThen操作符的特性:它会先调用bar.method3()来获取Completable实例,哪怕前面的method2()返回错误,这个方法调用还是会发生。但生产环境里,由于method2抛出了错误,andThen后面的Completable根本不会被订阅执行,所以method3里的打印逻辑永远跑不起来。

简单说:Mockito验证的是「bar.method3()被调用过」,但你真正想验证的是「method3返回的Completable的逻辑被执行过」——这俩完全是两回事。

解决方案:追踪Completable的订阅执行

要验证RxJava流的实际执行,我们需要给mock的Completable加个「执行标记」,来确认它的逻辑是否真的被触发了。这里用Mockito的Answer就能轻松实现:

修改后的测试代码

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import io.reactivex.Completable;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class FooTest {
    @Mock
    private Bar bar;
    @InjectMocks
    private Foo foo;

    @Test
    public void testExecuteAbortsAfterMethod2Error() throws Exception {
        // 模拟method1正常完成
        when(bar.method1()).thenReturn(Completable.complete());
        // 模拟method2抛出错误
        when(bar.method2()).thenReturn(Completable.error(new Exception()));

        // 用原子布尔值追踪method3的逻辑是否被执行
        AtomicBoolean method3LogicExecuted = new AtomicBoolean(false);
        // 当调用bar.method3()时,返回一个带追踪逻辑的Completable
        when(bar.method3()).thenAnswer(invocation ->
            Completable.fromAction(() -> {
                // 这里就是method3原本的逻辑,我们加个标记
                method3LogicExecuted.set(true);
                // 如果需要模拟原逻辑,也可以在这里调用实际的打印等操作
                // System.out.println("method 3");
            })
        );

        // 执行测试并断言错误
        foo.execute()
           .test()
           .assertError(Exception.class);

        // 验证方法调用情况(method1、method2各调用1次,method3确实被调用了)
        verify(bar, times(1)).method1();
        verify(bar, times(1)).method2();
        verify(bar, times(1)).method3();

        // 关键验证:method3的实际逻辑没有被执行
        assertThat(method3LogicExecuted.get()).isFalse();
    }
}

代码解释

  1. 原子布尔值追踪执行状态:用AtomicBoolean来记录method3的Completable逻辑是否被触发,它是线程安全的,适合测试场景。
  2. 用Answer自定义Completable:通过thenAnswer返回一个自定义的Completable,当这个Completable被订阅执行时,会把标记设为true。
  3. 双重验证:既验证了bar.method3()被调用过(符合代码逻辑),又验证了它的实际执行逻辑没有被触发(符合生产环境的行为)。

额外提示

如果你的RxJava流更复杂(比如涉及线程调度),还可以结合TestScheduler来控制流的执行时机,但对于你当前的场景,上面的方案已经足够解决问题了。

内容的提问来源于stack exchange,提问作者Lau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:32:02