android-模拟改造可观察到的错误

我正在使用Mockito测试Presenter功能.我已经构建了一些Fake API响应,并且已经成功测试了它们.

但是,当我想从Observable调用OnError时,不会调用它.

我在名为ApiCalls.java的类中具有以下功能:

public Observable<List<Person>> getPeople(String location)
{
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    APIService service = retrofit.create(APIService .class);

    return service.getPeople(location);
}

Presenter中的功能如下:

public void getPeople(final String location) {

    Observable observable= apiCalls.getPeople(location);

     observableResult.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<List<Person>>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void one rror(Throwable e) {
                    Log.w("ON ERROR",e.getMessage());
                    view.showError("An error has occurred");

                }

                @Override
                public void onNext(List<Person> people) {
                    view.refreshPeople(people);
                }
            });
}

然后,在单元测试中,我尝试执行以下操作:

   when(apiCalls.getPeople("London"))
            .thenReturn(Observable.error(new HttpException(buildResponse())));

   presenter.getPeople("London");

   verify(peopleView).showError(Mockito.anyString());

和buildResponse:

public Response buildResponse()
{
    String json = getJSONError();

    Response response = Response.error(403, ResponseBody.create(MediaType.parse("application/json") ,json));
    return response;
}

但是,当我测试时,出现以下消息错误:

Wanted but not invoked:
peopleView.showError(<any string>);
-> at com.lordwater.myapp.PeoplePresenterImpl.testError(PeoplePresenterTest.java:154)

编辑:在安装程序中我将计划程序设置为中间:

@Before
public void setUp() {

    RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() {
        @Override
        public Scheduler getMainThreadScheduler() {
            return Schedulers.immediate();
        }
    });

    presenter = new PeoplePresenterImpl(peopleView);
}

@After
public void tearDown() {
    RxAndroidPlugins.getInstance().reset();
}

解决方法:

您遇到的问题是您没有在RxJavaPlugins钩子中覆盖Schdeulers.io(),而仅是mainThread Scheduler:

@Override
public Scheduler getIOScheduler() {
    return Schedulers.immediate();
}

就像您说的那样,在测试实际的异步调用时,您必须等待结果,否则测试将最终没有结果,但是网络操作本身仍在单独的线程上进行,因此不会阻塞测试线程,并且测试已完成没有结果.

关于toBlocking(),当您要观察结果时,toBlocking()很有用(onNext()),这会将您的Obesrvable转换为BlockingObservable,其行为与内存集合中的行为类似,这意味着您需要调用:

 apiCalls.getPeople("London")
    .toBlocking()
    .first();

它将一直阻塞,直到找到答案为止,然后您可以断言等于该结果.
但是您的情况与此不同,您想通过onError()验证订阅者是否按预期方式工作,这意味着您也在测试订阅.

上一篇:java-有什么方法可以模拟pojo,然后在嘲笑中手动设置值?


下一篇:java-是否可以两次调用一个方法,首先调用实际实现,然后模拟结果?