2017-03-19 7 views
3

私はMockitoを使用してプレゼンターの機能をテストしています。私はいくつかの偽のAPIレスポンスを構築しており、正常にテストしました。モックretrofit観察可能なエラー

しかし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); 
} 

プレゼンター内の関数は以下の通りです:

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 onError(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) 

EDITを:私はInmediateにスケジューラを設定し、セットアップで:

@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(); 
} 
+0

スケジューラを即時に変更するには、テストセットアップで何かを行っていますか?そうでなければ、おそらくスレッドの問題です。 – Jahnold

+0

@Jahnold私はそれが問題だと思う。 '.observeOn'がスケジューラを切り替える可能性があり、テストスレッドは待機しません。 –

+0

@ TassosBassoukos私のエディションでは、SetUpでMainThreadSchedulerをInmediateに設定しました。それでも問題が.observeOnの場合、Observerを待機するためにテストスレッドをどのように作成できますか? – LordWater

答えて

3

あなたのケースでは問題があることですRxJavaPluginsフックでSchdeulers.io()をオーバーライドしませんでしたが、mainThreadスケジューラ:

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

あなたが言っていたように、実際の非同期呼び出しをテストするときは、結果を待つ必要があります。そうでなければテストは終了しますが、ネットワーク操作自体は別のスレッドで行われます。テストは結果なしで終了しました。 toBlocking()について

toBlocking()あなたは結果/秒(onNext())を観察したいとき、これはそれがだ、メモリコレクション内に多少似作用するBlockingObservableにごObesrvableを変換する便利なことは、あなたが呼び出す必要があります意味:

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

回答があるまでブロックしてから、assertEqualsこの結果を返すことができます。
ここでシナリオが異なる場合、サブスクライバがonError()と期待どおりに動作することを確認する必要があります。つまり、サブスクリプションもテストしています。

+0

あなたの説明をお寄せいただきありがとうございます。私はあなたの解決策を試してみました。 – LordWater