Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Mockito在单元测试中模拟ObservateTransformer_Java_Unit Testing_Mockito_Rx Java2 - Fatal编程技术网

Java 如何使用Mockito在单元测试中模拟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 {

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

这是要测试的类:

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"));