spring集成单元测试出站通道适配器



我有以下配置

<int:channel id="notificationChannel" datatype="com.mycompany.integration.NotificationMessage">
        <int:queue message-store="jdbc-message-store" capacity="1000" />
    </int:channel>
    <int:outbound-channel-adapter ref="notificationHandler"
        method="handle" channel="notificationChannel" >
        <int:poller max-messages-per-poll="100" fixed-delay="60000"
            time-unit="MILLISECONDS" >
            <int:transactional isolation="DEFAULT" />
        </int:poller>
    </int:outbound-channel-adapter>

现在我想对这个进行单元测试,我需要等待在测试中正确处理消息,我用拦截器尝试了它,但这不起作用,因为我只能同步消息传递,但不能同步消息的成功处理。在处理完成时实现发送回复,但这意味着将实现这只是为了使我的单元测试工作,在生产中,消息头中不会有replyChannel设置。我怎么能实现同步成功处理的请求,而不实现它在messageHandler?

如果您使用的是Spring Integration 2.2。X,你可以用一个建议…

public class CompletionAdvice extends AbstractRequestHandlerAdvice {
    private final CountDownLatch latch = new CountDownLatch(1);
    @Override
    protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
        Object result = callback.execute();
        latch.countDown();
        return result;
    }
    public CountDownLatch getLatch() {
        return latch;
    }
}

在您的测试环境中,使用bean工厂后置处理器将通知添加到适配器的处理程序中。

public class AddCompletionAdvice implements BeanFactoryPostProcessor {
    private final Collection<String> handlers;
    private final Collection<String> replyProducingHandlers;
    public AddCompletionAdvice(Collection<String> handlers, Collection<String> replyProducingHandlers) {
        this.handlers = handlers;
        this.replyProducingHandlers = replyProducingHandlers;
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for (String beanName : handlers) {
            defineAdviceAndInject(beanFactory, beanName, beanName + "CompletionAdvice");
        }
        for (String beanName : replyProducingHandlers) {
            String handlerBeanName = beanFactory.getAliases(beanName + ".handler")[0];
            defineAdviceAndInject(beanFactory, handlerBeanName, beanName + "CompletionAdvice");
        }
    }
    private void defineAdviceAndInject(ConfigurableListableBeanFactory beanFactory, String beanName, String adviceBeanName) {
        BeanDefinition serviceHandler = beanFactory.getBeanDefinition(beanName);
        BeanDefinition advice = new RootBeanDefinition(CompletionAdvice.class);
        ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(adviceBeanName, advice);
        serviceHandler.getPropertyValues().add("adviceChain", new RuntimeBeanReference(adviceBeanName));
    }
}

添加后置处理器到配置<bean class="foo.AddCompletionAdvice" />

最后,将通知注入您的测试用例

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class TestAdvice {
    @Autowired
    private CompletionAdvice fooCompletionAdvice;
    @Autowired
    private CompletionAdvice barCompletionAdvice;
    @Autowired
    private MessageChannel input;
    @Test
    public void test() throws Exception {
        Message<?> message = new GenericMessage<String>("Hello, world!");
        input.send(message);
        assertTrue(fooCompletionAdvice.getLatch().await(1, TimeUnit.SECONDS));
        assertTrue(barCompletionAdvice.getLatch().await(1, TimeUnit.SECONDS));
    }
}

,等待锁存器。

<int:publish-subscribe-channel id="input"/>
<int:outbound-channel-adapter id="foo" channel="input" ref="x" method="handle"/>
<int:service-activator id="bar" input-channel="input" ref="x"/>
<bean class="foo.AddCompletionAdvice">
    <constructor-arg name="handlers">
        <list>
            <value>foo</value>
        </list>
    </constructor-arg>
    <constructor-arg name="replyProducingHandlers">
        <list>
            <value>bar</value>
        </list>
    </constructor-arg>
</bean>
<bean id="x" class="foo.Foo" />

我将这些类添加到Gist

编辑:更新为最终消费者(无回复)和回复产生消费者提供一般案例

最新更新