【发布时间】:2017-04-09 05:01:58
【问题描述】:
我正在学习如何编写 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。我似乎还没有明白。
是否有一个特定的实例,我应该在何时使用、验证、如何测试可观察到的改造请求错误。
如果它说没有 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 模式,我正在尝试用它编写测试。谢谢。
【问题讨论】:
-
当你调用 getPopularMovies(1, FAKE_API_KEY) 你的 apiService 的哪个方法会被调用?你有没有用 mockito 模拟过这个方法??
-
@LeandroBorgesFerreira 我更新了我的问题
-
什么是投掷成功?测试还是 getPopularMovies Observable?我不确定您要做什么...您是否需要 apiService 返回一个引发异常的 Observable?你需要改变 Observable 来抛出你需要的异常
-
@LeandroBorgesFerreira 当它说 Mock 为空时,我有点理解。接口服务类中的函数为空。这就是
when(apiService.discover(SORT_BY_POPULARITY, PAGE, API_KEY))的精髓。我想测试错误,所以我做了这样的事情:(请检查更新的问题) -
@LeandroBorgesFerreira 如果我更改 Observable 以引发错误,你是说我应该更改 Object
APIServiceObservable 函数正在发射吗?
标签: android retrofit2 rx-java2