1

我有两个Completable同时在两个不同的线程上运行并访问共享资源。我想测试他们的行为,以便只有第一个运行某些代码,第二个以错误结束。

由于我Scheduler.trampoline()在测试中使用,这两个Completables 不能同时运行,而是按顺序运行,我无法对该代码进行单元测试。

例子,

    val subscription = userRepository.logout().test()
    val subscriptionSimultaneous = userRepository.logout().test()


    subscription
        .assertNoErrors()
        .assertComplete()

    subscriptionSimultaneous
        .assertError(someError)
        .assertNotComplete()

    verify(exactly = 1) { somethingThatMustRunOnlyOnce() }
4

1 回答 1

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 个 Completable logout()。有计数器可以计算logout()成功和失败的次数。blockingAwait正在等待所有 Completable 完成。运行此测试 100 次,如果您删除synchronized. onErrorComplete()是否有避免在所有 Completable 完成之前传播异常。

有趣的事实:如果您添加 getter 和 setterloggedOut并在其中使用它logout(),大多数情况下如果没有synchronized.

希望能帮助到你!

于 2018-12-13T13:51:28.373 回答