2017-04-07 6 views
1

Ich lerne, wie man Android-Unit-Tests schreibt. Und ich bin auf der Suche Beispiele: So, ich sah etwas wie folgt aus:Verstehen, wie man RxJava Observables prüft

@Test 
public void getPopularMoviesMakesApiCall() { 
    // given that the api service returns a response 
    1. when(apiService.discover(SORT_BY_POPULARITY, PAGE, API_KEY)).thenReturn(Observable.just(mDiscoverMoviesResponse)); 

    // when getPopularMovies is invoked 
    2. mRemoteRepository.getPopularMovies(1).subscribeWith(mMovieListTestSubscriber); 

    // then, verify that the api request is made and returns the expected response 
    3. verify(apiService).discover(SORT_BY_POPULARITY, PAGE, API_KEY); 
    4. mMovieListTestSubscriber.assertValue(mMovieList); 
} 

Ich habe versucht, es zu laufen, und ich bemerkte, Option 1 führt immer, Option 2 auch der Fall ist. Wenn jedoch Option 3 nicht mit den Informationen in Option 2, übereinstimmt, wird ein Fehler ausgegeben, der besagt, dass sie nicht identisch sind. Das bedeutet, dass Option 3 Option 2 bestätigt. Wenn ich falsch liege oder irgendetwas zu korrigieren ist, bitte erzählen. So schrieb ich etwas wie folgt aus:

@Test 
public void testBadHashException() throws Exception { 

    1. mRemoteRepository.getPopularMovies(1, FAKE_API_KEY).subscribeWith(mMovieListTestSubscriber); 

    2. mMovieListTestSubscriber.assertNoValues(); 
    3. mMovieListTestSubscriber.assertError(HttpException.class); 
} 

Dies ist, was ich bemerkt:

private List<Movie> mMovieList; 
private DiscoverMoviesResponse mDiscoverMoviesResponse; 

private MoviesRepository mRemoteRepository; 

private TestObserver<List<Movie>> mMovieListTestSubscriber; 
private TestObserver<Movie> mMovieTestSubscriber; 

@Mock 
MovieApiService apiService; 

Die oben wurden am Anfang erklärt und initialisiert durch einen Mockito @Before @annotation wie folgt aus:

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

    mRemoteRepository = new MoviesRemoteRepository(apiService); 

    mMovieTestSubscriber = new TestObserver<>(); 
    mMovieListTestSubscriber = new TestObserver<>(); 

    mMovieList = TestDataGenerator.generateMovieList(10); 
    mDiscoverMoviesResponse = TestDataGenerator.generateDiscoverMoviesResponse(mMovieList); 
} 

Hinweis: TestDataGenerator ist eine Hilfsklasse zum Generieren von Daten. Wie es dort gemacht wird, bekam er MovieList und bekam dann einen anderen, der der Hauptantwortkörper ist.

APIService: Die Nachrüstservice-Klasse. MoviesRepository: Eine Hilfsklasse zum Bearbeiten von Observablen in der Serviceklasse. Welche wird vom ViewModel verwendet?

Der zweite Test gibt mir java.lang.RuntimeException: No mock defined for invocation. Ich verstehe es noch nicht. Gibt es eine bestimmte Instanz, die ich verwenden sollte, wenn, überprüfen, wie ich für Observable Retrofit Request Fehler testen.

Wenn es keine Mock-Daten sagt, aber dann Mock-Daten generiert wurden, wenn dies erledigt ist. Oder soll es anders verspottet werden?

mMovieList = TestDataGenerator.generateMovieList(10); mDiscoverMoviesResponse = TestDataGenerator.generateDiscoverMoviesResponse(mMovieList);

Mehr zu meiner Beobachtung:

Ich wollte durch Mockito und ich bemerkte, der erste Test, der durchgemacht ausgeführt wurde, weil er tat:

1. when(apiService.discover(SORT_BY_POPULARITY, PAGE, API_KEY)).thenReturn(Observable.just(mDiscoverMoviesResponse));

Da die Fehler für die zweite Funktion zeigt java.lang.RuntimeException: No mock defined for invocation, es wurde festgestellt, dass die Methode innerhalb einer Klasse kann mit 0 verspottet werdenist es okay. Ich änderte dann meine testBadHashException wie folgt aussehen:

@Test 
public void testBadHashException() throws Exception { 

    0. when(apiService.discover(SORT_BY_POPULARITY, PAGE, API_KEY)).thenReturn(Observable.just(mDiscoverMoviesResponse)); 

    1. mRemoteRepository.getPopularMovies(1, FAKE_API_KEY).subscribeWith(mMovieListTestSubscriber); 

    2. mMovieListTestSubscriber.assertNoValues(); 
    3. mMovieListTestSubscriber.assertError(HttpException.class); 
} 

Statt eine Ausnahme zu werfen, warf er einen Erfolg.

schrieb ich die Fehlerprüfung:

@Test 
public void getPopularMoviesThrowsError() { 
    when(mMoviesRepository.getPopularMovies(PAGE)).thenReturn(Observable.<List<Movie>>error(new TimeoutException())); 

    // request movies 
    mMoviesViewModel.discoverMovies(true); 

    verify(mMoviesRepository).getPopularMovies(PAGE); 

    // check that empty view is hidden 
    assertFalse(mMoviesViewModel.emptyViewShowing.get()); 

    // check that loading view is hidden 
    assertFalse(mMoviesViewModel.moviesLoading.get()); 

    // check that error view is showing 
    assertTrue(mMoviesViewModel.errorViewShowing.get()); 
} 

Es ist ein Übersetzungsfehler hier: Observable.<List<Movie>>error(new TimeoutException())

Writing Tests in Android im Vergleich zu JavaScript sieht wirklich seltsam: when(mMoviesRepository.getPopularMovies(PAGE)).thenReturn(Observable.<List<Movie>>error(new TimeoutException()));

Es ist nicht Methode hier lösen können . Jede Hilfe, wie ich lernen oder verstehen kann, wie man Komponententests schreibt, wäre willkommen.Ich habe gerade das MVVM-Muster angenommen und ich versuche, Test damit zu schreiben. Vielen Dank.

+2

Wenn Sie getPopularMovies (1, FAKE_API_KEY) aufrufen, welche Methode Ihres apiService wird aufgerufen? Hast du diese Methode verspottet? –

+0

@LeandroBorgesFerreira Ich habe meine Frage aktualisiert –

+0

Was ist erfolgreich? Der Test oder die getPopularMovies Observable? Ich bin mir nicht sicher, was Sie tun möchten ... Benötigen Sie den apiService, um ein Observable zurückzugeben, das eine Ausnahme auslöst? Sie müssen das Observable ändern, um die Ausnahme zu werfen, die Sie benötigen –

Antwort

0

Wenn Sie einen Fehler auf Ihre beobachtbare senden können Sie es wie folgt erstellen:

when(mMoviesRepository.getPopularMovies(PAGE)).thenReturn( 
    Observable.create(new Observable.OnSubscribe<SomeClass>() { 
     @Override public void call(Subscriber<SomeCladd> subscriber) { 
      subscriber.onError(new Exception("some message!")); 
     } 
     })); 

diese Weise erhalten Sie eine Observable, die einen Fehler zurückgibt, so dass Sie

mMovieListTestSubscriber.assertError nennen

Das Problem, das Sie haben, ist, dass Sie Observable.just verwenden, um Ihre Observable zu erstellen ... So wird die Methode onError nie aufgerufen werden, nur die onNext.

Verwandte Themen