【问题标题】:Testing error handling with direct channels and source with poller使用轮询器测试直接通道和源的错误处理
【发布时间】:2019-04-23 11:51:56
【问题描述】:

我在 Spring Integration DSL 中实现了以下流程:

  1. 从 HTTP 获取提要
  2. 丰富 errorChannel 标头(在此处处理下游所有异常的点)。
  3. 将消息转换为集合
  4. 将集合拆分为单独的消息
  5. 将每条消息发送到下一个处理通道
@Bean
    public IntegrationFlow inboundHttpFlow(
        Puller puller,
        HeaderEnricher errorHandlingChannelHeaderEnricher,
        FeedTransformer feedTransformer,
        MessageChannel outputFeedIntegrationChannel
    ) {
        final Consumer<SourcePollingChannelAdapterSpec> pollingSpec = spec ->
            spec
                .poller(Pollers.cron(SCHEDULE_EVERY_HALF_MINUTE)
                    .errorChannel(INBOUND_ERROR_CHANNEL));

        return IntegrationFlows
            .from(puller, pollingSpec)
            .enrichHeaders(errorHandlingChannelHeaderEnricher)
            .transform(feedTransformer)
            .split()
            .channel(outputFeedIntegrationChannel)
            .get();
    }

我的 errorHandlingChannelHeaderEnricher 在哪里:

@Component
public class ErrorHandlingChannelHeaderEnricher implements HeaderEnricher {
    @Override
    public void accept(HeaderEnricherSpec spec) {
        spec.header(
            MessageHeaders.ERROR_CHANNEL,
            INBOUND_ERROR_CHANNEL,
            true
        );
    }
}

feedTransformer 在工作应用程序中抛出异常时,它会按预期设置 errorChannel。但是我不知道如何编写一个测试来测试抛出的异常是否进入标题中定义的 errorChannel

当我试图以给定的方式在测试中模拟它时,它不起作用,因为异常被抛出回调用者而不是 errorChannel

// given
Throwable transformerException = new IllegalStateException();
when(feedTransformerMock.apply(any())).thenThrow(transformerException);

// when
var testFeedMessage = MessageBuilder
    .withPayload(pullerResult)
    .build();

inboundHttpFlow.getInputChannel().send(testFeedMessage); // excetpion returns to caller here

// then
verify(errorHandlerSpy).accept(transformerException);

异常是典型的:

org.springframework.integration.transformer.MessageTransformationException: Failed to transform Message; nested exception is org.springframework.messaging.MessageHandlingException: nested exception is java.lang.IllegalStateException, failedMessage=GenericMessage [payload=test-payload, headers={errorChannel=inboundErrorChannel, id=f77a6a01-9bca-5af3-8352-7edb4c5e94b0, timestamp=1556019833867}]
, failedMessage=GenericMessage [payload=test-payload, headers={errorChannel=inboundErrorChannel, id=f77a6a01-9bca-5af3-8352-7edb4c5e94b0, timestamp=1556019833867}]

我假设由于 DirectChannel 和在这个测试示例中缺少轮询器与实际流程(使用轮询器)相比。 有什么方法可以模拟抛出异常并检查它是否真的进入了 header 中定义的 errorChannel?

【问题讨论】:

    标签: spring junit error-handling spring-integration spring-integration-dsl


    【解决方案1】:

    不清楚您要测试什么。

    为什么需要测试框架?

    您不需要丰富标头,因为轮询器上已经有一个错误通道。

    你是对的;发送到DirectChannel 将导致向调用者抛出异常。

    如果您真的想测试框架,请模拟 Puller 而不是发送到输入通道。

    【讨论】:

    • 感谢您的回复。我不想测试框架。我有我的自定义错误处理程序,它在我的错误流中用作消息处理程序,它在 errorChannel 上触发,在这种情况下是 innboundErrorChannel。在那个集成测试中,我想确保我的错误处理程序将处理集成流中的异常(例如在转换期间)。我正在寻找一种在测试中触发该流程的方法,因为实际上它是由 cron Poller 轮询的,我必须等待。 Mocking Puller 很好,但如何触发呢?我也在考虑在这之间添加额外的频道。
    • 如果你只是想测试你的错误流,为什么不直接构建一个ErrroMessage(带有MessagingException有效载荷和failedMessage)并将其发送到INBOUND_ERROR_CHANNEL。您还可以将轮询器设为 @Bean 并在测试用例中将其替换为简单的 on。
    • 原因是因为我想在集成测试中测试错误流,以确保流中发生的异常将由我的错误处理程序处理(在该流中处理它们的全局点)。注入轮询器可能是个好主意,但我怎样才能使轮询器变得简单并在测试开始时强制它启动并避免将异常返回给调用者?
    • 只需将 cron poller bean 替换为 fixedRate poller bean。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2010-12-12
    相关资源
    最近更新 更多