如何使用MUnit在Mule Flow中模拟Java组件

时间:2015-04-28 03:30:56

标签: java unit-testing mule munit

我正在尝试使用MUnit对我的一个子流进行单元测试,我需要模拟一个自定义Java组件,但我无法这样做。

我的子流程如下所示

Subflow under test

<sub-flow name="ProcessCSVFlow" tracking:enable-default-events="true">
    <transformer ref="enrichWithHeaderAndEndOfFileTransformer" doc:name="headerAndEOFEnricher" />
    <set-variable variableName="outputfilename" value="#['Mercury'+server.dateTime.year+server.dateTime.month+server.dateTime.dayOfMonth+server.dateTime.hours +server.dateTime.minutes+server.dateTime.seconds+'.csv']" doc:name="outputfilename"/>
    <sftp:outbound-endpoint exchange-pattern="one-way" connector-ref="DestinationSFTP" host="${destination.host}" port="22" responseTimeout="10000" doc:name="DestinationSFTP"
    outputPattern="#[outputfilename]" path="${destination.path}" user="${destination.username}" password="${destination.password}"/>
    <!-- <component class="nz.co.mightyriver.creditreport.component.ArchiveOutputComponent" doc:name="Archive"/> -->
    <gzip-compress-transformer/>
    <sftp:outbound-endpoint exchange-pattern="one-way" connector-ref="InputSFTP" host="${source.host}" port="22" responseTimeout="10000" doc:name="SourceArchiveSFTP" 
    outputPattern="#[outputfilename].gzip" path="Archive" user="${source.username}" password="${source.password}"/>
    <component doc:name="Delete Read File">
        <singleton-object class="nz.co.mightyriver.creditreport.component.DeleteProcessedFileComponent">
            <property key="host" value="${source.host}"/>
            <property key="username" value="${source.username}"/>
            <property key="password" value="${source.password}"/>
            <property key="workingDirectory" value="${source.path}"/>
        </singleton-object>
    </component>
    <parse-template location="successmessagetemplate.txt" doc:name="Success Template"/>
    <smtp:outbound-endpoint host="${smtp.host}" port="${smtp.port}" user="${smtp.from.address}" password="${smtp.from.password}" 
                            to="${smtp.to.address}" from="${smtp.from.address}" subject="${mail.success.subject}" responseTimeout="10000" 
                            doc:name="SuccessEmail" connector-ref="Gmail"/>
    <logger message="Process completed successfully" level="INFO" doc:name="Logger"/>
</sub-flow>

这是我失败的单元测试

@Test
public void givenAValidPayload_whenFlowIsInvoked_itShouldSendPayloadToDestinationSFTPOnlyOnce() throws Exception {
    destinationSFTP.thenReturnSameEvent();
    sourceArchiveSFTP.thenReturnSameEvent();
    deleteProcessedFileComponent.thenReturnSameEvent();
    successEmail.thenReturnSameEvent();


    MuleEvent testEvent = PropertyEnricher.enrich(testEvent(IOUtils.toInputStream("hello,dummy,payload"))).get();

    runFlow(PROCESS_CSV_FLOW, testEvent);

    verifyCallOfMessageProcessor("outbound-endpoint")
            .ofNamespace("sftp")
            .withAttributes(attribute("name").ofNamespace("doc").withValue("DestinationSFTP"))
            .times(1);

}

我试图嘲笑组件

deleteProcessedFileComponent = whenMessageProcessor("component")
            .withAttributes(attribute("name").ofNamespace("doc").withValue("Delete Read File"));

我尝试了一些变体,但没有一个有效,我猜一个组件不是 MessageProcessor

我得到的例外情况如下

org.mule.api.lifecycle.InitialisationException: Component has not been initialized properly, no flow constuct.
at org.mule.component.AbstractComponent.initialise(AbstractComponent.java:218)
at org.mule.processor.chain.AbstractMessageProcessorChain.initialise(AbstractMessageProcessorChain.java:80)
at org.mule.processor.chain.AbstractMessageProcessorChain$$FastClassByCGLIB$$38c17d88.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.mule.munit.common.mp.WrapperMunitMessageProcessorInterceptor.invokeSuper(WrapperMunitMessageProcessorInterceptor.java:71)
at org.mule.munit.common.mp.WrapperMunitMessageProcessorInterceptor.invokeSuper(WrapperMunitMessageProcessorInterceptor.java:63)
at org.mule.munit.common.mp.WrapperMunitMessageProcessorInterceptor.intercept(WrapperMunitMessageProcessorInterceptor.java:49)
at org.mule.processor.chain.SubflowInterceptingChainLifecycleWrapper$$EnhancerByMUNIT$$c8ca2508.initialise(<generated>)
at org.mule.munit.runner.functional.FunctionalMunitSuite.initialiseSubFlow(FunctionalMunitSuite.java:269)
at org.mule.munit.runner.functional.FunctionalMunitSuite.runFlow(FunctionalMunitSuite.java:259)
at nz.co.mightyriver.ProcessCsvTest.givenAValidPayload_whenFlowIsInvoked_itShouldSendPayloadToDestinationSFTPOnlyOnce(ProcessCsvTest.java:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

1 个答案:

答案 0 :(得分:1)

所以你的模拟没有问题它实际上是完美的。 问题在于Mule和MUnit的一点点。

简短的回答,现在没有解决方法。 虽然有一个解决方法!

创建一个新的xml(以使其与生产代码分开) 将流(不是子流)添加到新的xml。 在刚刚添加的流程中,对子流程执行flow-ref。 从您测试,而不是执行runFlow(PROCESS_CSV_FLOW),执行runFlow(&#34; the_flow_you_created&#34;)。

答案越长越好:

子流程不是真正的流程,它们甚至不共享父类。因此他们表现得有点不同。 MUnit做了一些事情来使这个事实对用户透明。

事实证明我们做得不够,我会在MUnit项目中创建一个jira来解决这个问题。但希望你能够继续测试。