Java 如何使用Mockito在单元测试中模拟ObservateTransformer
为了获得可重用和可测试的rxjava代码,我使用ObservateTransformer分离了部分代码。它在生产中运行良好,但是测试它并不像预期的那么容易,因为我似乎无法模拟那些可观察的转换器 这是要测试的类:Java 如何使用Mockito在单元测试中模拟ObservateTransformer,java,unit-testing,mockito,rx-java2,Java,Unit Testing,Mockito,Rx Java2,为了获得可重用和可测试的rxjava代码,我使用ObservateTransformer分离了部分代码。它在生产中运行良好,但是测试它并不像预期的那么容易,因为我似乎无法模拟那些可观察的转换器 这是要测试的类: import io.reactivex.Observable; import io.reactivex.ObservableTransformer; import io.reactivex.subjects.PublishSubject; public class Cut {
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.Observable;
导入io.reactivex.observetTransformer;
导入io.reactivex.subjects.PublishSubject;
公共课削减{
private PublishSubject发射器=PublishSubject.create();
私人ITransformerProvider transformerProvider;
公共切割(ITransformerProvider transformerProvider){
this.transformerProvider=transformerProvider;
}
public void writeNewText(字符串文本){
.onNext(文本);
}
公共可观测getActualText(){
返回发射器
.compose(transformerProvider.getObservableTransformer());
}
类MyActualObjectableTransformer实现ITransformerProvider{
@凌驾
公共ObservateTransformer getObservateTransformer(){
//执行我不想在单元测试中执行的操作,例如REST调用
返回null;
}
}
}
导入io.reactivex.observetTransformer;
公共接口ITransformerProvider{
ObservateTransformer GetObservateTransformer();
}
让我们假设生产性MyActualObjectableTransformer需要模拟,以便进行简单的单元测试
这是一个简单的测试,试图测试当我交新的文本时会发生什么。我确实意识到这项测试毫无意义,它只是为了说明我的问题:
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"));
}
}
公共类文本测试{
@嘲弄
私人ITransformerProvider transformerProvider;
@嘲弄
私有可观测变换器可观测变换器;
私人测试观察者;
私人切割;
@以前
公共作废设置(){
initMocks(this);
当(transformerProvider.GetObservateTransformer())。然后返回(ObservateTransformer);
when(observectransformer.apply(any())。然后return(observectable.just(“mockedText”);
testObserver=新的testObserver();
切割=新切割(变压器供应商);
cut.getActualText()
.observeOn(Schedulers.trampoline())
.订阅(
newText->testObserver.onNext(newText)
,error->Assert.fail(error.getMessage());
}
@试验
public void testGetActualText(){
剪切、写入文本(“忽略文本”);
testObserver.assertValueAt(0,text->text.equals(“mockedText”);
}
}
问题是在运行测试时,发射器没有订阅服务器
分析了调用堆栈之后,我想我知道问题出在哪里了。据我所知,当subscribe被调用时,链中所有可观测的subscribe都被调用。如果没有我的ObservateTransformer模拟,就会发生这种情况,这就是为什么它在生产中运行良好
但是,当我添加模拟时:
when(observectransformer.apply(any())。然后return(observectable.just(“mockedText”)
一旦调用subscribe for,它就会发出一个新的值,订阅链永远不会完成。
所以我的问题是,我如何模拟一个可观察对象,而不让它在订阅期间发出值?我想Observable.just或BehaviorSubject不是一个好办法,因为就我有限的RxJava知识而言,它在这种情况下的行为与预期的一样。有什么想法吗?我想到的最简单的解决方案就是不要用Mockito来模仿,而是自己模仿: 私有ObservateTransformer ObservateTransformer=text->text.map(忽略->模拟文本)
我知道这篇文章有点老了,但它是搜索“mockito ObservateTransformer”的最高结果,所以我认为添加一个让你不断模仿的解决方案可能是个好主意 就像在实代码中调用transformer函数一样,您需要从
操作
组合它。该方法本身不返回可观测值,因此您必须告诉它如何到达该值。您可以通过使用observetTransformer
lambda模拟该方法来实现这一点:
when(observableTransformer.apply())
.thenReturn(upstream -> upstream.map(action -> "mockedString"));
when(observableTransformer.apply())
.thenReturn(upstream -> upstream.map(action -> "mockedString"));