2017-05-11 4 views
2

私はユニットテストでは新しいです、そして、私はrxアンドロイドでレトロフィットをユニットテストしています。私はapiからアクセストークンを取得している1つの観測可能性を持っており、私は要求を送信するためにレトロフィットを使用してそれを使用します。私はここにNULLポインタ例外が原因取得していますことは、私のコードです:改造機とRxのアンドロイドでユニットテスト

@RunWith(MockitoJUnitRunner.class) 
public class AuthenticationTokenGetterTest { 
    @Mock 
    AuthenticatorInterface authenticatorservice; 
    @InjectMocks 
    AuthenticationTokenGetter tokengetter; 

    @Test 
    public void testtokkengetter() { 
     when(authenticatorservice.servicecall(anyString(), anyString())).thenReturn(
       Observable.just("44fffffggggggg")); 

     Observable<String> obs = tokengetter.getToken(); 
     TestSubscriber<String> testsubscriber = new TestSubscriber<>(); 
     obs.subscribe(testsubscriber); 
     testsubscriber.assertNoErrors(); // Here I get exception 
     List<String> value = testsubscriber.getOnNextEvents(); 
    } 

} 

しかし、私はjava.lang.NullPointerExceptionがすべての時間を取得しています。私のエラーがある

@CheckResult 
    public Observable<String> getToken() { 
     return service.servicecall(key, code) 
       .subscribeOn(Schedulers.newThread()) 
       .doOnNext(new Action1<String>() { 
        public void call(String token) { 
         savedToken = token; 
        } 
       }) 
       .observeOn(AndroidSchedulers.mainThread()); 
    } 

: と私の観察可能なコードは、私がテストしていたある

java.lang.AssertionError: Unexpected onError events: 1 

    at rx.observers.TestSubscriber.assertNoErrors(TestSubscriber.java:308) 
    at AuthenticationTokenGetterTest.testtokkengetter(AuthenticationTokenGetterTest.java:47) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) 
Caused by: java.lang.NullPointerException 
    at rx.android.schedulers.LooperScheduler$HandlerWorker.schedule(LooperScheduler.java:77) 
    at rx.android.schedulers.LooperScheduler$HandlerWorker.schedule(LooperScheduler.java:91) 
    at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.schedule(OperatorObserveOn.java:190) 
    at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber$1.request(OperatorObserveOn.java:147) 
    at rx.Subscriber.setProducer(Subscriber.java:209) 
    at rx.Subscriber.setProducer(Subscriber.java:205) 
    at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.init(OperatorObserveOn.java:141) 
    at rx.internal.operators.OperatorObserveOn.call(OperatorObserveOn.java:75) 
    at rx.internal.operators.OperatorObserveOn.call(OperatorObserveOn.java:40) 
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:46) 
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) 
    at rx.Observable.subscribe(Observable.java:8759) 
    at rx.Observable.subscribe(Observable.java:8726) 
.AuthenticationTokenGetterTest.testtokkengetter(AuthenticationTokenGetterTest.java:45) 
+0

スタックトレースも提供してください。 – jakubbialkowski

+0

@jakubbialkowski編集 – SimpleMan

答えて

3

あなたは、Androidルーパークラスに依存するAndroidSchedulers.mainThread()を使用している、なぜNULLポインタのthats。複数のスレッドを使用している単体テストを作成しないで、同じスレッド上のすべてを実行してください!

これは、スケジューラ注入を行うことで解決できます。 AuthenticationTokenGetterクラスはmainThreadSchedulerインスタンスをコンストラクタで渡されたScheduler参照によって取得する必要があります。したがって、通常のコードではmainThreadSchedulerでオブジェクトを作成し、テスト中はSchedulerですべてを同期的に実行するオブジェクトを作成してください。

RxJava/RxAndroidSchedulersHookを使用して、スケジューラを無効にすることもできます。/ ovverideスケジューラを注入する方法を説明する

@edit いくつかの記事:

https://medium.com/@peter.tackage/overriding-rxandroid-schedulers-in-rxjava-2-5561b3d14212

https://medium.com/@peter.tackage/an-alternative-to-rxandroidplugins-and-rxjavaplugins-scheduler-injection-9831bbc3dfaf

これらのソリューションのどちらも、それはこれらの記事はRxJava2このことを目的としているにもかかわらず、長所と短所だましたアプローチはRxJava1でも有効です(スケジューラのフック/プラグインはRx2では少し違って動作します)

+0

あなたのお返事ありがとうございます。私はあなたの最初の部分を理解しましたが、2番目の部分を理解できませんでした。通常のコードも編集する必要がありますか? – SimpleMan

+0

@SimpleMan私はすべてを明確にすべきである私の答えにいくつかの記事を追加しました – Than

+0

ありがとう、私の問題は解決されました。 – SimpleMan

0

私はthiを使用していますsの技術:

  1. BaseSchedulerProvider(父)
  2. ImmediateSchedulerProvider(テスト)
  3. SchedulerProvider(アプリケーション)

BaseSchedulerProvider:私はテストのために使用

public interface BaseSchedulerProvider { 

    @NonNull 
    Scheduler computation(); 

    @NonNull 
    Scheduler io(); 

    @NonNull 
    Scheduler ui(); 
} 

ImmediateSchedulerProvider:

私はこのような私のPresenterTest Iセットアップで私のプレゼンター

public class SchedulerProvider implements BaseSchedulerProvider { 

    // Prevent direct instantiation. 
    public SchedulerProvider() { 
    } 

    @Override 
    @NonNull 
    public Scheduler computation() { 
     return Schedulers.computation(); 
    } 

    @Override 
    @NonNull 
    public Scheduler io() { 
     return Schedulers.io(); 
    } 

    @Override 
    @NonNull 
    public Scheduler ui() { 
     return AndroidSchedulers.mainThread(); 
    } 
} 

に使用

public class ImmediateSchedulerProvider implements BaseSchedulerProvider { 

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

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

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

そしてSchedulerProvider:

public class TopicPresenterTest { 

      @Mock 
      private RemoteDataSource mRemoteDataSource; 

      @Mock 
      private TopicContract.View mView; 

      private BaseSchedulerProvider mSchedulerProvider; 

      TopicPresenter mPresenter; 

      List<Topics> mList; 

      @Before 
      public void setup() { 
      MockitoAnnotations.initMocks(this); 

        Topics topics = new Topics(1, "Discern The Beach"); 
        Topics topicsTwo = new Topics(2, "Discern The Football Player"); 
        mList = new ArrayList<>(); 
        mList.add(topics); 
        mList.add(topicsTwo); 
//ADD IMMEDIATESCHEDULERPROVIDER !!!!!!!!!!!!!!! 
        mSchedulerProvider = new 
        ImmediateSchedulerProvider(); 

        mPresenter = new TopicPresenter(mRemoteDataSource, mView, mSchedulerProvider); 

      } 

      @Test 
      public void fetchData() { 

       when(mRemoteDataSource.getTopicsRx()) 
         .thenReturn(rx.Observable.just(mList)); 

       mThemePresenter.fetch(); 

       InOrder inOrder = Mockito.inOrder(mView); 
       inOrder.verify(mView).setLoadingIndicator(false); 
       inOrder.verify(mView).showTopics(mList); 

      } 

} 

そして、私のプレゼンター

public class TopicPresenter { 

     @NonNull 
     private BaseSchedulerProvider mSchedulerProvider; 

     public TopicPresenter(@NonNull RemoteDataSource remoteDataSource, @NonNull TopicContract.View view) { 
        this.mRemoteDataSource = checkNotNull(remoteDataSource, "remoteDataSource"); 
        this.mView = checkNotNull(view, "view cannot be null!"); 
        this.mSchedulerProvider = new SchedulerProvider(); 
//ADD COMPOSITESUBSCRITPTION !!!!!!  
        mSubscriptions = new CompositeSubscription(); 

        mView.setPresenter(this); 
     } 
} 

であなたがmy complete example in GitHubを確認することができますし、 this article.

関連する問題