防止RxJava将我的自定义异常包装到复合对象中

时间:2019-09-10 16:52:45

标签: java exception rx-java

我被赋予了使用RxJava进行实现的任务,并以这种方式进行保护,以防万一发生任何错误,它将被包装到自定义异常中。

问题是,无论我做什么,RxJavaPlugin都决定将我的异常包装到CompositeException中,即使只有一个。测试失败。

我已经尝试了在Google上可以找到的所有方法,直到实际上覆盖了RxJavaPlugin的全局错误处理程序,但它忽略了尝试的更改。

应在撰写本文时将其抛出的功能的实现

Single<BigDecimal> summarizeConfirmedTransactions() throws SummarizationException {
        try{
            Observable<Transaction> observableTransactions = transactions.get()
                    .doOnError(throwable -> {
                        Exceptions.propagate(throwable);
                    });
            Observable<Confirmation> observableConfirmations = confirmations.get()
                    .doOnError(throwable -> {
                        Exceptions.propagate(throwable);
                    });
            return Observable.zip(observableTransactions, observableConfirmations, (t, c) -> new ConfirmableTransaction(t.transactionId, c.isConfirmed, t.value))
                    .filter(confirmableTransaction -> confirmableTransaction.isConfirmed)
                    .map(t -> t.value)
                    .reduce(BigDecimal::add)
                    .toSingle()
                    .doOnError(throwable -> {
                        Exceptions.propagate(throwable);
                    });
        }catch(Exception e)
        {
            throw new SummarizationException(e.getMessage());
        }

测试中的断言失败,因为最终引发的异常是CompositeException,其中包含单个异常。我必须将其设置为SummarizationException.class

非常感谢。

编辑: 根据要求,这里是用于测试解决方案的代码。我不允许修改它。

    @Test
    public void shouldWrapErrorIntoException() {
        final ConfirmedTransactionSummarizer summarizer =
                new ConfirmedTransactionSummarizer(ALL_CONFIRMED::transactions, () -> Observable.error(new RuntimeException("Booom")));


        summarizer
                .summarizeConfirmedTransactions()
                .subscribe(testObserver);

        testObserver.assertError(SummarizationException.class);
        testObserver.assertErrorMessage("Booom");
    }

PS。我已经问过这个任务的提供者,他说“我是唯一遇到这种问题的人”,并且我不应该使事情变得过于复杂并寻求最简单的解决方案。...这会导致3个异常的综合异常-一个其中一个是我的异常包装,另外两个是通过测试代码插入的RuntimeException实例。

2 个答案:

答案 0 :(得分:1)

好吧,经过更多的挖掘,并在朋友的帮助下,我设法确定了任务的意图:

我应该在那里做的事情:

Single<BigDecimal> summarizeConfirmedTransactions() throws SummarizationException {


            Observable<Transaction> observableTransactions = transactions.get();
            Observable<Confirmation> observableConfirmations = confirmations.get();
            return Observable.zip(observableTransactions, observableConfirmations,
                    (t, c) -> new ConfirmableTransaction(c.isConfirmed, t.value))
                    .filter(confirmableTransaction -> confirmableTransaction.isConfirmed)
                    .map(t -> t.value)
                    .reduce(BigDecimal::add)
                    .toSingle()
                    .onErrorResumeNext(th -> Single.error(new SummarizationException(th.getMessage())));
    }

感谢大家的见解,案例已结案:)

tl:dr我不应该将错误“包装”到引发的异常中,而是将它们包装到包含异常的错误响应中。

答案 1 :(得分:0)

一种解决方法是在测试中使用try-catch块,解包CompositeException然后断言捕获的异常。

fun testSummarizationException() {
    try {
        summarizeConfirmedTransactions()
    } catch (ex: Exception) {
        val customException = (ex as? CompositeException)?.exceptions?.get(0)
        //  assert to make sure thrown exception is of custom type
        assert(customException is SummarizationException)
    }
}

这是CompositeException展开以获取自定义异常的地方。

  

val customException =(例如CompositeException)?. exceptions?.get(0)

如果允许,将

Exception类型转换为CompositeException。如果此类型不允许强制转换,则它将返回null并通过测试。