Spring Integration: how to unit test a poller advice

安稳与你 提交于 2020-08-12 02:54:25

问题


I'm trying to unit test an advice on the poller which blocks execution of the mongo channel adapter until a certain condition is met (=all messages from this batch are processed).

The flow looks as follow:

IntegrationFlows.from(MongoDb.reactiveInboundChannelAdapter(mongoDbFactory,
            new Query().with(Sort.by(Sort.Direction.DESC, "modifiedDate")).limit(1))
                    .collectionName("metadata")
                    .entityClass(Metadata.class)
                    .expectSingleResult(true),
            e -> e.poller(Pollers.fixedDelay(Duration.ofSeconds(pollingIntervalSeconds))
                    .advice(this.advices.waitUntilCompletedAdvice())))
            .handle((p, h) -> {
                this.advices.waitUntilCompletedAdvice().setWait(true);
                return p;
            })
            .handle(doSomething())
            .channel(Channels.DOCUMENT_HEADER.name())
            .get();

And the following advice bean:

@Bean
public WaitUntilCompletedAdvice waitUntilCompletedAdvice() {
    DynamicPeriodicTrigger trigger = new DynamicPeriodicTrigger(Duration.ofSeconds(1));
    return new WaitUntilCompletedAdvice(trigger);
}

And the advice itself:

public class WaitUntilCompletedAdvice extends SimpleActiveIdleMessageSourceAdvice {

    AtomicBoolean wait = new AtomicBoolean(false);

    public WaitUntilCompletedAdvice(DynamicPeriodicTrigger trigger) {
        super(trigger);
    }

    @Override
    public boolean beforeReceive(MessageSource<?> source) {
        if (getWait())
            return false;
        return true;
    }

    public boolean getWait() {
        return wait.get();
    }

    public void setWait(boolean newWait) {
        if (getWait() == newWait)
            return;

        while (true) {
            if (wait.compareAndSet(!newWait, newWait)) {
                return;
            }
        }
    }
}

I'm using the following test for testing the flow:

    @Test
    public void testClaimPoollingAdapterFlow() throws Exception {
        // given
        ArgumentCaptor<Message<?>> captor = messageArgumentCaptor();
        CountDownLatch receiveLatch = new CountDownLatch(1);
        MessageHandler mockMessageHandler = mockMessageHandler(captor).handleNext(m -> receiveLatch.countDown());
        this.mockIntegrationContext.substituteMessageHandlerFor("retrieveDocumentHeader", mockMessageHandler);
        LocalDateTime modifiedDate = LocalDateTime.now();
        ProcessingMetadata data = Metadata.builder()
                .modifiedDate(modifiedDate)
                .build();
        assert !this.advices.waitUntilCompletedAdvice().getWait();

        // when
        itf.getInputChannel().send(new GenericMessage<>(Mono.just(data)));

        // then
        assertThat(receiveLatch.await(10, TimeUnit.SECONDS)).isTrue();
        verify(mockMessageHandler).handleMessage(any());
        assertThat(captor.getValue().getPayload()).isEqualTo(modifiedDate);
        assert this.advices.waitUntilCompletedAdvice().getWait();
    }

Which works fine but when I send another message to the input channel, it still processes the message without respecting the advice.

Is it intended behaviour? If so, how can I verify using unit test that the poller is really waiting for this advice?


回答1:


itf.getInputChannel().send(new GenericMessage<>(Mono.just(data)));

That bypasses the poller and sends the message directly.

You can unit test the advice has been configured by calling beforeReceive() from your test

Or you can create a dummy test flow with the same advice

IntegationFlows.from(() -> "foo", e -> e.poller(...))
       ...

And verify that just one message is sent.



来源:https://stackoverflow.com/questions/63363310/spring-integration-how-to-unit-test-a-poller-advice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!