我正在学习如何编写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模式和我试图用它编写测试。感谢。
答案 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。