测试 RxJava 回调函数



我正在尝试测试用Rxjava运算符之一的回调函数编写的代码。这是我想要测试的原始代码

@Override
public Observable<List<User>> getUsers() {
    UserDataStore userDataStore = userDataStoreFactory.createCloudDataStore();
    return userDataStore.getUsers().map(userEntityDataMapper::transform);
}

在上面的代码中,有一个"map"运算符,其回调函数将通过调用userEntityDataMapper.transform()方法将原始对象转换为另一个对象。在这里,我想测试用户实体数据映射器的转换方法必须是调用。这是我尝试检查userEntityDataMapper.transform()方法调用与否的代码。

@Test
public void testGetUsersHappyCase() {
    List<UserEntity> userEntityList = new ArrayList<>();
    userEntityList.add(new UserEntity());
    given(mockUserDataStore.getUsers()).willReturn(Observable.just(userEntityList));
    List<User> userList = new ArrayList<>();
    given(mockUserEntityDataMapper.transform(userEntityList)).willReturn(userList);
    given(mockUserDataStoreFactory.createCloudDataStore()).willReturn(mockUserDataStore);
    Observable observable = userDataRepository.getUsers();
    verify(mockUserDataStoreFactory).createCloudDataStore();
    verify(mockUserDataStore).getUsers();
    TestObserver<List<UserEntity>> testObserver = new TestObserver<>();
    TestScheduler testScheduler = new TestScheduler();
    observable.subscribeOn(testScheduler).observeOn(testScheduler).subscribeWith(testObserver);
    verify(mockUserEntityDataMapper).transform(any(List.class));
}

我在堆栈溢出和论坛上检查了许多类似的问题,但无法找到我问题的确切解决方案。

更新:这是我为解决问题所做的更改。

@Test
public void testGetUsersHappyCase() {
    List<UserEntity> userEntityList = new ArrayList<>();
    userEntityList.add(new UserEntity());
    given(mockUserDataStore.getUsers()).willReturn(Observable.just(userEntityList));
    List<User> userList = new ArrayList<>();
    given(mockUserEntityDataMapper.transform(userEntityList)).willReturn(userList);
    userDataRepository.getUsers().test().assertNoErrors();
    verify(mockUserDataStoreFactory).createCloudDataStore();
    verify(mockUserDataStore).getUsers();
    verify(mockUserEntityDataMapper).transform(userEntityList);
}

感谢@tynn test(( 方法的提示。我在 https://github.com/googlesamples/android-architecture-components 的BasicRxJavaSample演示中也发现了同样的东西。

您必须订阅流才能执行它。这就像在可观察对象上调用test()一样容易完成。这将为您提供一个TestObserver

除此之外,您没有任何理由使用 TestScheduler .在您的情况下,这实际上是问题所在。您没有调用triggerActions(),因此您的流根本不执行。

如果您没有修改正在测试的代码中的任何计划程序,则在测试中也忽略这些计划程序。如果需要更改它,最好创建一个规则,将每个Schedulers设置为同步版本。您可以在RxJavaPlugins类中找到此的二传手。

Tynn的回答是正确的,你应该听听那里的建议。重构的测试如下所示:

@org.junit.Test
public void testUserDataRepository() throws Exception {
    //arrange
    List<UserEntity> userEntityList = new ArrayList<>();
    userEntityList.add(new UserEntity());
    given(mockUserDataStore.getUsers()).willReturn(Observable.just(userEntityList));
    List<User> userList = new ArrayList<>();
    given(mockUserEntityDataMapper.transform(userEntityList)).willReturn(userList);
    given(mockUserDataStoreFactory.createCloudDataStore()).willReturn(mockUserDataStore);
    //act
    TestObserver<List<User>> testObservable = userDataRepository.getUsers().test();

    //assert
    verify(mockUserDataStoreFactory).createCloudDataStore();
    verify(mockUserDataStore).getUsers();
    verify(mockUserEntityDataMapper).transform(any(List.class));
}

然而,这种类型的白盒测试存在更大的问题 - 测试已经退化为被测系统的重新实现。

如果UserEntityDataMapper是轻量级的,您可以在测试中使用它的真实版本。然后你的测试变成了一个黑盒测试,可以说有更多的价值。您将知道对UserEntityDataMapper#transform的调用是通过对List<User>正确结果的断言发生的:

@org.junit.Test
public void testUserDataRepository() throws Exception {
    //arrange
    List<UserEntity> userEntityList = new ArrayList<>();
    userEntityList.add(new UserEntity());
    given(mockUserDataStore.getUsers()).willReturn(Observable.just(userEntityList));
    List<User> userList = new ArrayList<>();
    given(mockUserDataStoreFactory.createCloudDataStore()).willReturn(mockUserDataStore);
    //act
    TestObserver<List<User>> testObservable = userDataRepository.getUsers().test();
    //assert
    testObservable.assertResult(userList);
}

相关内容

  • 没有找到相关文章

最新更新