MUnit тестирует поток с помощью сборщика-агрегатора

Я пытаюсь написать тесты MUnit для своих потоков Mule. Я хочу написать тест для следующего потока

Полный поток мулов

<flow name="DownloadFTPFileIntoLocalFlow" processingStrategy="synchronous" tracking:enable-default-events="true">
    <quartz:inbound-endpoint jobName="Source-File-Scheduler" cronExpression="${source.pollingfrequency}" startDelay="10000" responseTimeout="10000" doc:name="Quartz">
        <quartz:endpoint-polling-job>
            <quartz:job-endpoint ref="InputSFTPEndpoint"/>
        </quartz:endpoint-polling-job>
    </quartz:inbound-endpoint>
    <logger message="DownloadFTPFileIntoLocalFlow #[payload.getClass().getName()]" level="INFO" doc:name="Logger"/>
    <set-property propertyName="MULE_CORRELATION_GROUP_SIZE" value="#[java.lang.Integer.MAX_VALUE]" doc:name="GroupsizeForExceptionAggregator"/>
    <set-property propertyName="MULE_CORRELATION_ID" value="#[java.util.UUID.randomUUID().toString()]" doc:name="corelationIdForExceptionAggregator"/>
    <set-variable variableName="originalPayload" value="#[payload]" doc:name="originalPayload"/>
    <byte-array-to-object-transformer doc:name="Byte Array to Object"/>
    <flow-ref name="ProcessCSVFlow" doc:name="ProcessCSVFlow" />
    <exception-strategy ref="Default_Exception_Strategy" doc:name="DownloadFTPFileIntoLocalFlow Strategy"/>
</flow>


 <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"/>
    <!-- <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}"/>
    <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="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>

Блок обработки исключений

<catch-exception-strategy name="Default_Exception_Strategy">
    <flow-ref name="ExceptionHandlingSubflow" doc:name="ExceptionHandlingSubflow"/>
</catch-exception-strategy>

<sub-flow name="ExceptionHandlingSubflow" tracking:enable-default-events="true">
    <collection-aggregator timeout="60000" failOnTimeout="false" doc:name="Exception Aggregator"/>
    <logger message="Exception has occured Payload is #[payload] and Message is #[message]" level="ERROR" doc:name="Logger"/>
    <parse-template location="errormessagetemplate.txt" doc:name="Error 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.failure.subject}" responseTimeout="10000" 
                            doc:name="ErrorEmail" connector-ref="Gmail"/>
</sub-flow>

Интересный момент - это подпоток исключения, особенно сборщик-агрегатор.

Мой модульный тест

@Test
public void whenMultipleExceptionsOccurInFlow_itShouldSendOnlyOneFailureEmail() throws Exception {
    whenMessageProcessor("collection-aggregator")
            .withAttributes(attribute("name").ofNamespace("doc").withValue("Exception Aggregator")).thenReturnSameEvent();

    destinationSFTP.thenThrow(new RuntimeException("Dummy Exception destinationSFTP"));

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

    runFlow("DownloadFTPFileIntoLocalFlow", testEvent);

    verifyCallOfMessageProcessor("outbound-endpoint").ofNamespace("smtp")
            .withAttributes(attribute("name").ofNamespace("doc").withValue("ErrorEmail"))
            .times(1);
}

Теперь, если я не имитирую агрегатор коллекций, мой тест не проходит, я могу понять, что это сложно, поскольку агрегатор имеет "паузу" внутри него и, следовательно, не является идеальным кандидатом для модульного теста, однако с технической точки зрения Я хочу понять, что вызывает сбой модульного теста (когда сборщик-агрегатор не имитируется).

Мой тест не проходит, если сборщик-агрегатор не высмеивается.

junit.framework.AssertionFailedError: On smtp:outbound-endpoint.Expected 1 but got 0 calls
    at junit.framework.Assert.fail(Assert.java:50)
    at org.mule.munit.common.mocking.MunitVerifier.times(MunitVerifier.java:86)
    at nz.co.mightyriver.ProcessCsvTest.whenMultipleExceptionsOccurInFlow_itShouldSendOnlyOneFailureEmail(ProcessCsvTest.java:100)
    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)

person Sudarshan    schedule 27.04.2015    source источник


Ответы (1)


Итак, я пытался воспроизвести эту проблему:

Производственный код

<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="9090" doc:name="HTTP Listener Configuration"/>
    <flow name="stack-munit-and-aggregationFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
        <set-payload value="#['lalero_' + new java.util.Date().toString()]" doc:name="Set Payload"/>
        <flow-ref name="stack-munit-and-aggregationSub_Flow" doc:name="stack-munit-and-aggregationSub_Flow"/>
        <set-payload doc:name="Set Payload" value="#[payload.toString()]"/>
    </flow>
    <sub-flow name="stack-munit-and-aggregationSub_Flow">
        <collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator" timeout="10"/>
    </sub-flow>

Тестовый код

package org.mule.munit;

import org.junit.Assert; import org.junit.Test; import org.mule.api.MuleEvent; import org.mule.api.MuleException; import org.mule.munit.runner.functional.FunctionalMunitSuite;

public class TheTest extends FunctionalMunitSuite {

    @Test
    public void aTest() throws MuleException, Exception {    MuleEvent event = runFlow("stack-munit-and-aggregationFlow", testEvent(""));

    String payload = (String) event.getMessage().getPayload();

    Assert.assertTrue(payload.contains("lalero"));
    } }

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

Думаю, проблема могла в другом. Не могли бы вы поделиться своим кодом, чтобы я мог продолжить расследование?

Мир предупреждений из-за проблемы, обнаруженной в: Как имитировать Java-компонент в Mule Flow с помощью MUnit

Вы можете столкнуться с проблемой, если попытаетесь напрямую протестировать свой подпоток ExceptionHandlingSubFlow. Но поскольку вы не делали этого в своем примере кода, я не думаю, что эти два отношения связаны.

Ваше здоровье!

person Dds    schedule 29.04.2015
comment
Большое спасибо за проявленный интерес, обновил свой вопрос запрошенными деталями. Кроме того, в прошлый раз я неправильно напечатал исключение (хотя не знаю, как я испортил), поэтому теперь мое утверждение не выполняется, если маршрутизатор агрегации не имитируется. - person Sudarshan; 30.04.2015
comment
Привет! Насколько я понимаю, похоже, что ошибка в потоке с MP агрегации (который, кстати, вы не публиковали). В любом случае я бы посоветовал вам попробовать воспроизвести свой тест MUnit, где вы можете отлаживать потоки мулов. Если он терпит неудачу, когда он не имитируется (агрегация), вероятно, что-то в полезной нагрузке, достигающей этого MP, не является ожидаемым (я считаю исключением). На данный момент я не вижу ничего, что указывало бы на ошибку MUnit :( - person Dds; 04.05.2015
comment
Спасибо, я добавил блок обработки исключений, который использует сборщик-агрегатор, было бы неплохо, если бы вы могли посмотреть. - person Sudarshan; 05.05.2015
comment
поэтому я не вижу фактических ошибок в коде, каково содержимое сообщения, когда оно попадает в MP агрегации? - person Dds; 05.05.2015