2016-06-24 14 views
1

Wie man eine Methode vortäuscht, die Callback-Objekt und Aufrufer dieser Methode verwendet, um Ergebnisse an andere Callbacks zu delegieren. Hier in meinem Szenario erstelle ich Rx Single daraus.Wie man eine Methode vortäuscht, die Callback-Objekt und Aufrufer verwendet, Callback verwenden, um Ergebnis zu delegieren

1. RecentDataModel.java

public class RecentDataModel { 

public void getRecentData(RecentDataAdapter recentDataAdapter) { 
    // Get data from database 
    // Invoke if success 
    recentDataAdapter.onSuccess() 
    // Invoke if error 
    recentDataAdapter.onError() 

} 
} 

2. RecentDataAdapter.java

public class RecentDataAdapter { 
    onSuccess(List<String> recents); 
    onError(); 
} 

3. RecentPresenter

public class RecentPresenter { 
public Single<List<String>> getRecentsSingle() { 
    return Single.create(new Single.OnSubscribe<List<String>>() { 
      @Override 
      public void call(final SingleSubscriber<? super List<String>> singleSubscriber) { 
       mRecentDataModel.getRecentData(new RecentDataAdapter() { 
        @Override 
        public void onSuccess(List<String> keywordList) { 
         singleSubscriber.onSuccess(keywordList); 
        } 
       }); 
      } 
     }); 
} 
} 

4. RecentTestCase

public class RecentPresenterTest { 

    @Mock 
    RecentDataModel recentModel; 

    @Test 
    public void testLoadRecent() { 
     doAnswer(new Answer() { 
      @Override 
      public List<String> answer(InvocationOnMock invocation) throws Throwable { 
       List<String> recents = new ArrayList<>(); 
       recents.add("Recent1"); 
     recents.add("Recent2"); 
       return recents; 
      } 
     }).when(recentModel).getRecentData(any(RecentDataAdapter.class)); 

     RecentPresenter recentProvider = new RecentPresenter(null, null, prefModel); 

     Action1 onNextListener = mock(Action1.class); 

     recentProvider.getRecentsSingle.subscribe(onNextListener); 

     ArgumentCaptor<List<String>> listCaptor = ArgumentCaptor.forClass((Class) List.class); 

     verify(onNextListener, timeout(5000)).call(listCaptor.capture()); 
     assertNotNull(listCaptor.getValue()); 
     assertEquals(listCaptor.getValue().get(0), "Recent1"); 
    } 

} 

Hinweis:

  1. keinen Zugang zu RecentDataModel hat und daher keine neuen Verfahren wie einführen können: List<String> getRecentData();

  2. Obwohl Verfahren ResentPresenter.getRecentsSingle() macht keine Geschäftslogik. Aber es wird mit anderen Methoden in der Klasse verbunden, um die Ausgabe zu erzeugen. Also verspotten RecentDataModel ist notwendig.

  3. -Test wird in folgenden Zeile "verify(onNextListener, timeout(5000)).call(listCaptor.capture());" scheitern, weil während spöttisch ich bin Bereitstellung any(RecentDataAdapter.class) aufgrund der singleSubscriber.onSuccess(keywordList); nie aufgerufen wird.

+0

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen über diese benötigt. –

Antwort

1

Das Problem ist, dass Sie Ihren Rückruf nicht auf Ihrem Adapter aufrufen. Da der Rückruf nie aufgerufen wird, wird Single.success nie aufgerufen. So wird die Single nicht an die ausgestellte Liste gemeldet. Und dann dein Überprüfungstimeout.

Um das Problem zu beheben, müssen Sie die onSuccess Callback-Methode in Ihrem Mock nennen:

doAnswer(new Answer() { 
     @Override 
     public Void answer(InvocationOnMock invocation) throws Throwable { 
      List<String> recents = new ArrayList<>(); 
      recents.add("Recent1"); 
      recents.add("Recent2"); 
      invocation.getArguments()[0].onSuccess(recents); 
      return null; 
     } 
}).when(recentModel).getRecentData(any(RecentDataAdapter.class)); 
+0

Danke @durursteisen. Muss ich cast "invocation.getArguments() [0]" in "SingleSubscriber >" eingeben, um onSuccess() darauf aufzurufen. Bitte antworten –

+0

Dank dwursteisen funktioniert es für mich so: ((RecentDataAdapter) invocation.getArguments() [0]). OnSuccess (recents) ;. Vielen Dank, Mann. –