我有两个Completable
同时在两个不同的线程上运行并访问共享资源。我想测试它们的行为,以便只有第一个运行某些代码,而第二个运行却有错误。
由于我在测试中使用Scheduler.trampoline()
,所以两个Completable
不能同时运行,而是按顺序运行,因此我无法对该代码进行单元测试。
示例
val subscription = userRepository.logout().test()
val subscriptionSimultaneous = userRepository.logout().test()
subscription
.assertNoErrors()
.assertComplete()
subscriptionSimultaneous
.assertError(someError)
.assertNotComplete()
verify(exactly = 1) { somethingThatMustRunOnlyOnce() }
答案 0 :(得分:1)
我实际上是在努力进行这样的测试。
public class RxTest {
@Test
public void testConcurrency() {
Logout logout = new Logout();
AtomicInteger logoutCount = new AtomicInteger(0);
AtomicInteger errorCount = new AtomicInteger(0);
Completable logoutCompletable = Completable.fromAction(() -> logout.logout())
.subscribeOn(Schedulers.io())
.doOnComplete(() -> logoutCount.addAndGet(1))
.doOnError(error -> errorCount.addAndGet(1))
.onErrorComplete();
int tries = 50;
Completable[] arrayOfLogoutCompletables = new Completable[tries];
for (int i = 0; i < tries; i++) {
arrayOfLogoutCompletables[i] = logoutCompletable;
}
// run all in parallel and wait for all to finish
Completable.mergeArray(arrayOfLogoutCompletables).blockingAwait();
assertEquals(1,logoutCount.get());
assertEquals(tries - 1, errorCount.get());
}
private static class Logout {
private boolean loggedOut = false;
/**
* if you remove synchronized test will fail!!
*/
private synchronized void logout() {
if (loggedOut) throw new IllegalStateException();
loggedOut = true;
}
}
}
测试在Schedulers.io()
上同时运行多达50个Completables,每个测试都调用logout()
。有些计数器可以计算logout()
成功和失败的次数。 blockingAwait
正在等待所有Completables完成。
运行此测试100次,如果您删除synchronized
,它可能会在20%的时间内失败。 onErrorComplete()
可以避免在所有Completables完成之前传播异常。
有趣的事实:如果将getter和setter添加到loggedOut
并在logout()
中使用它,那么在大多数情况下,如果没有synchronized
,它将失败。
希望有帮助!