[英]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.