Spring Integration: методы тестов терпят неудачу, если выполняются вместе

Рабочий процесс моего приложения добавляет заголовок сообщения, затем маршрутизирует сообщение в зависимости от другого заголовка и отправляет сообщение дальше по течению. Мои тесты для этого рабочего процесса успешны по отдельности, но не при совместном выполнении, хотя кажется, что я сбросил все соответствующие объекты.

Рабочий процесс весенней интеграции:

<int:header-enricher input-channel="workflowStart" output-channel="headerEnriched">
    <int:header name="correlationId" expression="headers.id.toString()" />
</int:header-enricher>

<int:header-value-router input-channel="headerEnriched" header-name="messageType">
    <int:mapping value="stp" channel="stpChannel" />
    <int:mapping value="nonStp" channel="nonStpChannel" />
</int:header-value-router>

<int:publish-subscribe-channel id="nonStpChannel"   />
<int:publish-subscribe-channel id="stpChannel" apply-sequence="true"/>

<int:chain input-channel="nonStpChannel" output-channel="systemChannel1" id="nonStpChainBlockA"> 
    <!-- do something -->
</int:chain> 

<int:chain input-channel="stpChannel" output-channel="systemChannel3" id="stpChainBlockA"> 
    <!-- do something -->
</int:chain> 

Тестовый класс Java:

@Autowired 
    private MessageChannel workflowStart;
    @Autowired
    private MessageHandler systemChannel1OutputHandler; 
    @Autowired
    private MessageHandler systemChannel3OutputHandler; 

    @Value("/xml/tradeStp.xml")
    private Resource stpMessageResource;
    private String stpMessage;
    @Value("/xml/tradeNonStp.xml")
    private Resource nonStpMessageResource;
    private String nonStpMessage;


    @Before
    public void setup() throws Exception {
        reset(systemChannel1OutputHandler);
        reset(systemChannel3OutputHandler);
        stpMessage = IOUtils.toString(stpMessageResource.getInputStream());
        nonStpMessage = IOUtils.toString(nonStpMessageResource.getInputStream());
    }

    @Test
    public void nonStpMessageWorkflow1Test() {
        Message<String> m = MessageBuilder
                .withPayload(nonStpMessage)
                .setHeaderIfAbsent("messageType", "nonStp")
                .build();       
        workflowStart.send(m);
        verify(systemChannel1OutputHandler, times(1)).handleMessage(any(Message.class));    
    }

    @Test
    public void stpMessageWorkflow2Test() {
        Message<String> m = MessageBuilder
                .withPayload(stpMessage)
                .setHeaderIfAbsent("messageType", "stp")
                .build();
        workflowStart.send(m);
        verify(systemChannel3OutputHandler, times(1)).handleMessage(any(Message.class));
    }

И тестовый контекст:

<import resource="classpath:/spring/workflow.xml"/>

<int:outbound-channel-adapter channel="systemChannel1" ref="systemChannel1OutputHandler" method="handleMessage"/>
<bean id="systemChannel1OutputHandler" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="org.springframework.integration.core.MessageHandler"/>
</bean> 
<int:outbound-channel-adapter channel="systemChannel3" ref="systemChannel3OutputHandler" method="handleMessage"/>
<bean id="systemChannel3OutputHandler" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="org.springframework.integration.core.MessageHandler"/>
</bean>

<int:outbound-channel-adapter channel="headerEnriched" ref="headerEnricherOutputHandler" method="handleMessage"/>
<bean id="headerEnricherOutputHandler" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="org.springframework.integration.core.MessageHandler"/>
</bean>

Если я запускаю оба теста вместе, первый тест завершается успешно, а второй завершается с ошибкой с сообщением:

    Wanted but not invoked:
messageHandler.handleMessage(<any>);
-> at com.company.integration.com.company.export.config.InterfaceTest.stpMessageWorkflow2Test(InterfaceTest.java:81)
Actually, there were zero interactions with this mock.

Я пытался отлаживать разными способами. Проблема, кажется, сразу после маршрутизатора значений заголовка и перед цепочкой. Последний вывод отладки для второго теста — это «postSend» на канале headerEnriched. Любые советы очень приветствуются.

ОБНОВЛЕНИЕ: мне не удалось включить дополнительный outputHandler, который у меня есть в моем контексте, для другого теста, который я включил сейчас. После удаления headerEnricherOutputHandler все тесты проходят нормально. Однако я до сих пор не понимаю, почему это вызывает проблемы при совместном запуске тестов.


person evgeni    schedule 13.11.2012    source источник


Ответы (2)


У меня были проблемы с Mockito при использовании любого (класса). Где у вас есть

verify(systemChannel3OutputHandler, times(1)).handleMessage(any(Message.class));

работает ли он, если вы удалите класс, например:

verify(systemChannel3OutputHandler, times(1)).handleMessage(any());
person Dave Richardson    schedule 13.11.2012
comment
Спасибо за идею. Это не сработало, так как проблема, похоже, на стороне пружины, по какой-то причине сообщение не отправляется вниз по течению. - person evgeni; 13.11.2012

Я не могу воспроизвести вашу проблему со следующим, что существенно не отличается от ваших тестов...

<int:header-value-router input-channel="headerEnriched" header-name="messageType">
    <int:mapping value="stp" channel="stpChannel" />
    <int:mapping value="nonStp" channel="nonStpChannel" />
</int:header-value-router>

<int:publish-subscribe-channel id="nonStpChannel"   />
<int:publish-subscribe-channel id="stpChannel" apply-sequence="true"/>

<int:chain input-channel="stpChannel" output-channel="systemChannel1">
    <int:transformer expression="'bar'"/>
</int:chain>

<int:chain input-channel="nonStpChannel" output-channel="systemChannel3">
    <int:transformer expression="'bar'"/>
</int:chain>

<int:channel id="systemChannel1" />
<int:channel id="systemChannel3" />

<int:outbound-channel-adapter channel="systemChannel1" ref="systemChannel1OutputHandler" method="handleMessage"/>
<bean id="systemChannel1OutputHandler" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="org.springframework.integration.core.MessageHandler"/>
</bean> 
<int:outbound-channel-adapter channel="systemChannel3" ref="systemChannel3OutputHandler" method="handleMessage"/>
<bean id="systemChannel3OutputHandler" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="org.springframework.integration.core.MessageHandler"/>
</bean>

.

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class Foo {

    @Autowired
    private MessageChannel headerEnriched;

    @Autowired
    private MessageHandler systemChannel1OutputHandler;

    @Autowired
    private MessageHandler systemChannel3OutputHandler;

    @Test
    public void test10() {
        Message<String> foo = MessageBuilder.withPayload("foo")
                .setHeader("messageType", "stp").build();
        headerEnriched.send(foo);
        verify(systemChannel1OutputHandler).handleMessage(any(Message.class));
    }

    @Test
    public void test30() {
        Message<String> foo = MessageBuilder.withPayload("foo")
                .setHeader("messageType", "nonStp").build();
        headerEnriched.send(foo);
        verify(systemChannel3OutputHandler).handleMessage(any(Message.class));
    }
}

Оба теста у меня проходят нормально.

person Gary Russell    schedule 14.11.2012
comment
Спасибо за помощь. На самом деле мне не удалось включить один компонент в мой контекст (см. обновление), что вызывает проблему. Однако до сих пор не ясно, почему возникает проблема. - person evgeni; 14.11.2012
comment
Поскольку у вас есть два потребителя, подписанные на «headerEnriched», диспетчер по умолчанию будет циклически обрабатывать запросы, поэтому ваше второе тестовое сообщение отправляется новому адаптеру. Если вы действительно планировали эту двойную подписку, вам нужно сделать «headerEnriched» каналом публикации-подписки. - person Gary Russell; 15.11.2012