了解如何测试RxJava Observables

时间:2017-04-07 23:44:20

标签: android retrofit2 rx-java2

我正在学习如何编写android单元测试。而且,我正在看例子:所以,我看到了这样的事情:

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

我试图运行它,我注意到选项1总是执行,选项2也执行。但是,如果选项3不符合选项2中的信息, 它会抛出一个错误,说它们不一样。这意味着选项3确认选项2.如果我错了或者有任何要纠正的地方,请 一定要告诉。所以,我写了这样的话:

@Test
public void testBadHashException() throws Exception {

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

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

这是我注意到的:

private List<Movie> mMovieList;
private DiscoverMoviesResponse mDiscoverMoviesResponse;

private MoviesRepository mRemoteRepository;

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

@Mock
MovieApiService apiService;

上面的那些,被声明在顶部,并由Mockito @Before @annotation初始化,如下所示:

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

注意:TestDataGenerator是一个用于生成数据的辅助类。当它在那里完成时,他得到了MovieList,然后得到了另一个主要响应体。

APIService:改造服务类。 MoviesRepository:一个辅助类,用于在服务类中操作Observable。 ViewModel使用它。

第二次测试一直给我java.lang.RuntimeException: No mock defined for invocation。我似乎还没理解它。 是否有一个特定的实例,我应该在验证时如何测试Observable Retrofit Request Errors。

如果它没有说Mock数据,那么完成此操作后就会生成Mock数据。或者它应该被嘲笑不同?

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

更多关于我的观察:

我正在经历Mockito而且我注意到,第一次经历的测试正在执行,因为他做了:

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

由于第二个函数的错误显示java.lang.RuntimeException: No mock defined for invocation,因此声明了该方法 在课堂上可以使用when("some method").thenReturn()来嘲笑它。然后我修改了我的testBadHashException看起来像这样:

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

而不是抛出异常,它取得了成功。

我重写了错误测试:

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

此处存在编译错误:when(mMoviesRepository.getPopularMovies(PAGE)).thenReturn(Observable.<List<Movie>>error(new TimeoutException()));

此处无法解决方法:Observable.<List<Movie>>error(new TimeoutException())

与JavaScript相比,在Android中编写测试看起来非常奇怪。任何有关如何学习或理解如何编写单元测试的帮助将不胜感激。我刚收养了 MVVM模式和我试图用它编写测试。感谢。

1 个答案:

答案 0 :(得分:0)

如果您需要向Observable发送错误,可以像这样创建:

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

这样你就会有一个Observable返回一个错误,你可以调用

mMovieListTestSubscriber.assertError

你遇到的问题是你使用Observable.just来创建你的Observable ......所以onError方法永远不会被调用,只是onNext。