测试rxjava回调函数

时间:2018-01-06 13:37:47

标签: android unit-testing mockito rx-java2

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

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />

<div class="row">
  <div class="col-sm-2 leftMenu"></div>
  <div class="col-sm-10 pageContent"></div>
</div>

在上面的代码中有一个“map”运算符,它的回调函数将通过调用@Override public Observable<List<User>> getUsers() { UserDataStore userDataStore = userDataStoreFactory.createCloudDataStore(); return userDataStore.getUsers().map(userEntityDataMapper::transform); } 方法将原始对象转换为另一个。 这里我想测试userEntityDataMapper的转换方法必须调用。这是我试图检查userEntityDataMapper.transform()方法是否调用的代码。

userEntityDataMapper.transform()

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

更新 以下是我为解决问题所做的更改。

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

感谢@tynn提示test()方法。我在{{3}}上找到的BasicRxJavaSample演示中也发现了同样的事情。

2 个答案:

答案 0 :(得分:2)

您必须订阅流才能执行它。这可以像在observable上调用test()一样容易。这将为您提供TestObserver

除此之外,您没有任何理由使用TestScheduler。在你的情况下,它实际上是问题。您没有致电triggerActions(),因此您的信息流根本没有被执行。

如果您没有修改您正在测试的代码中的任何调度程序,请在测试中忽略这些调度程序。如果需要更改它,则应该更好地创建规则,将Schedulers设置为同步版本。您可以使用RxJavaPlugins类找到此设置器。

答案 1 :(得分:0)

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);
}
相关问题