복붙노트

[SPRING] 스프링 통합 유닛 테스트 아웃 바운드 채널 어댑터

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>

이제는 유닛 테스트를하고 싶습니다. 테스트에서 메시지가 올바르게 처리 될 때까지 기다릴 필요가 있습니다. 인터셉터를 사용하여 시도했지만 메시지 전달 만 동기화 할 수는 있지만 성공적으로 처리 할 수는 없으므로 작동하지 않습니다. 메시지. procesing이 끝났을 때 응답을 보내라.하지만 이것이 내 유닛 테스트를하기 위해서만 구현한다는 것을 의미 할 것이다. 생산에서 message-header에 replyChannel이 설정되지 않을 것이다. 어떻게 messageHandler에 구현하지 않고 요청을 성공적으로 처리 할 때 동기화를 실현할 수 있습니까?

해결법

  1. ==============================

    1.Spring Integration 2.2.x를 사용하고 있다면, 이것을 조언으로 할 수 있습니다 ...

    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 factory post processor를 사용하여 어댑터의 핸들러에 advice를 추가하십시오.

    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));
        }
    
    }
    

    포스트 프로세서를 config 에 추가하십시오.

    마지막으로 테스트 케이스에 조언을 삽입하십시오.

    @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에 추가했다.

    편집 : 궁극적 인 소비자 (응답 없음)에 대한 일반 사례를 제공하고 소비자를 생성하는 답장을 위해 업데이트되었습니다.

  2. from https://stackoverflow.com/questions/16277487/spring-integration-unit-test-outbound-channel-adapter by cc-by-sa and MIT license