繁体   English   中英

如何使用 Mockito 在单元测试中模拟 ObservableTransformer

[英]How to mock an ObservableTransformer in unit tests using Mockito

为了获得可重用和可测试的 rxjava 代码,我使用 ObservableTransformers 分离了部分代码。 它在生产中运行良好,但是测试它并不像预期的那么容易,因为我似乎无法模拟那些 ObservableTransformers。

这是要测试的类:

import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;
import io.reactivex.subjects.PublishSubject;

public class Cut {

    private PublishSubject<String> emitter = PublishSubject.create();
    private ITransformerProvider transformerProvider;

    public Cut(ITransformerProvider transformerProvider) {
        this.transformerProvider = transformerProvider;
    }

    public void writeNewText(String text){
        emitter.onNext(text);
    }

    public Observable<String> getActualText(){
        return emitter
                .compose(transformerProvider.getObservableTransformer());
    }

    class MyActualObservableTransformer implements ITransformerProvider {
        @Override
        public ObservableTransformer<String, String> getObservableTransformer() {
            //does something I do not want to execute in unit test, e.g. REST call
            return null;
        }
    }
}
import io.reactivex.ObservableTransformer;

public interface ITransformerProvider {
    ObservableTransformer<String, String> getObservableTransformer();
}

让我们假设富有成效的 MyActualObservableTransformer 需要模拟以进行简单的单元测试。

这是一个简单的测试,试图测试当我交出新文本时会发生什么。 我确实意识到测试没有意义,它只是浓缩以显示我的问题:

public class TextTest {

    @Mock
    private ITransformerProvider transformerProvider;
    @Mock
    private ObservableTransformer<String, String> observableTransformer;

    private TestObserver<String> testObserver;
    private Cut cut;


    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);

        when(transformerProvider.getObservableTransformer()).thenReturn(observableTransformer);
        when(observableTransformer.apply(any())).thenReturn(Observable.just("mockedText"));

        testObserver = new TestObserver<>();
        cut = new Cut(transformerProvider);

        cut.getActualText()
            .observeOn(Schedulers.trampoline())
            .subscribe(
                    newText -> testObserver.onNext(newText)
                    , error -> Assert.fail(error.getMessage()));
    }

    @Test
    public void testGetActualText(){
        cut.writeNewText("ignoredText");
        testObserver.assertValueAt(0, text -> text.equals("mockedText"));
    }
}

问题是在运行测试时,发射器没有订阅者。

分析了调用堆栈后,我想我知道问题出在哪里了。 所以据我了解,当 subscribe 被调用时,链中所有 observable 的订阅都会被调用。 如果没有我的 ObservableTransformer 模拟,就会发生这种情况,这就是它在生产中运行良好的原因。

但是,当我添加我的模拟时:

当(observableTransformer.apply(any())).thenReturn(Observable.just("mockedText"));

一旦 subscribe 被调用,它就会发出一个新值并且订阅链永远不会完成。 所以我的问题是,如何在订阅期间模拟 observable 而不发出值? 我猜 Observable.just 或 BehaviorSubject 不是要走的路,因为它在这种情况下按预期运行,就我仍然有限的 RxJava 知识而言。 有任何想法吗?

我想出的最简单的解决方案是不使用 Mockito 进行模拟并自己模拟它:

私有 ObservableTransformer observableTransformer = text -> text.map(ignore -> "mockedText");

我知道这篇文章有点旧,但它是搜索“mockito ObservableTransformer”的最高结果,所以我认为添加一个让你保持 Mockito-ing 的解决方案可能是个好主意。

就像在实际代码中调用转换器函数一样,您需要从Action组合它。 该方法本身不返回 Observable,因此您必须告诉它如何到达那里。 您可以通过使用ObservableTransformer lambda 模拟该方法来做到这一点:

when(observableTransformer.apply())
  .thenReturn(upstream -> upstream.map(action -> "mockedString"));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM