【问题标题】:Spring Integration: tests methods fail if executed togetherSpring Integration:如果一起执行,测试方法会失败
【发布时间】:2012-11-13 14:42:55
【问题描述】:

我的应用程序的工作流程是添加消息头,然后根据另一个头路由消息并将消息发送到下游。我对这个工作流的测试单独成功,但在一起执行时没有成功,尽管我似乎已经重置了所有相关对象。

spring 集成工作流程:

<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.

我尝试过以各种方式进行调试。问题似乎就在 header-value-router 之后和链之前。第二个测试的最后一个调试输出是 headerEnriched 通道上的“postSend”。 非常欢迎任何建议。

更新: 我没有在我的上下文中包含一个额外的 outputHandler 用于另一个测试,我现在已经包含了。通过删除 headerEnricherOutputHandler 所有测试运行良好。但是,我仍然不明白为什么在一起运行测试时这会导致问题。

【问题讨论】:

    标签: spring unit-testing spring-integration


    【解决方案1】:

    我在使用任何(类)的 Mockito 时遇到了问题。你在哪里

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

    如果您删除该类,它是否可以使用,例如:

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

    【讨论】:

    • 感谢您的想法。这不起作用,因为问题似乎出在弹簧方面,由于某种原因,消息没有被发送到下游。
    【解决方案2】:

    我无法通过以下内容重现您的问题,这与您的测试似乎没有实质性不同...

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

    两个测试对我来说都运行良好。

    【讨论】:

    • 感谢您的帮助。实际上,我没有在我的上下文中包含一个 bean(请参阅更新),这导致了问题。但仍不清楚为什么会出现此问题。
    • 由于您有两个消费者订阅了“headerEnriched”,默认调度程序将轮询重新请求,因此您的第二条测试消息将发送到“新”适配器。如果您真的想要这种双重订阅,则需要将“headerEnriched”设为发布-订阅通道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 2013-12-01
    • 2018-07-04
    • 2017-03-18
    • 2021-10-30
    • 1970-01-01
    • 2019-09-17
    相关资源
    最近更新 更多