Mock a message from a 3rd party system in Mule using MUnit

1.1k views Asked by At

I'm writing a test suite (using Munit) for a Mule application that is processing new data coming from an instance of Magento. One of my flows is polling Magento for new customers and the message it receives is of type: com.magento.api.CustomerCustomerEntity

I'm wondering how I'd mock this so that in my test case, when the Magento message processor is called I can return a payload of the same type and make the appropriate assertations?

Currently my Munit test looks as follows:

<mock:config name="mock_MagentoToSalesforce" doc:name="Mock configuration"/>
<spring:beans>
    <spring:import resource="classpath:MagentoToSalesforce.xml"/>
    <spring:bean id="myBean" name="myBean" class="com.magento.api.CustomerCustomerEntity">
        <spring:property name="email" value="[email protected]"/>
    </spring:bean>
</spring:beans>

<munit:test name="MagentoToSalesforce-test-getCustomersFlowTest" description="Test">
    <mock:when config-ref="mock_MagentoToSalesforce" messageProcessor=".*:.*" doc:name="Mock">
        <mock:with-attributes>
            <mock:with-attribute whereValue-ref="#[string:Get New Customers]" name="doc:name"/>
        </mock:with-attributes>
        <mock:then-return payload-ref="#[app.registry.myBean]"/>
    </mock:when>
    <flow-ref name="getCustomers" doc:name="Flow-ref to getCustomers"/>
</munit:test>

And the flow I'm trying to test is:

<flow name="getCustomers" processingStrategy="synchronous">
    <poll doc:name="Poll">
        <fixed-frequency-scheduler frequency="30" timeUnit="SECONDS"/>
        <watermark variable="watermark" default-expression="#[new org.mule.el.datetime.DateTime().plusYears(-30)]" update-expression="#[new org.mule.el.datetime.DateTime().plusYears(-0)]" selector-expression="#[new org.mule.el.datetime.DateTime(payload.created_at, 'yyyy-MM-dd HH:mm:ss')]"/>
        <magento:list-customers config-ref="Magento" filter="dsql:SELECT confirmation,created_at,created_in,customer_id,dob,email,firstname,group_id,increment_id,lastname,middlename,password_hash,prefix,store_id,suffix,taxvat,updated_at,website_id FROM CustomerCustomerEntity WHERE updated_at &gt; '#[flowVars.watermark]'" doc:name="Get New Customers"/>
    </poll>
    <foreach doc:name="For Each">
        <data-mapper:transform config-ref="MagentoCustomer_To_SalesforceContact" doc:name="Map Customer to SFDC Contact">
            <data-mapper:input-arguments>
                <data-mapper:input-argument key="ContactSource">Magento</data-mapper:input-argument>
            </data-mapper:input-arguments>
        </data-mapper:transform>
        <flow-ref name="upsertSalesforceContactFlow" doc:name="upsertSalesforceContactFlow"/>
    </foreach>
</flow>

Update following Ryan's answer:

Changed the expression to return a payload of #[ent = new com.magento.api.CustomerCustomerEntity(); ent.setEmail('[email protected]'); return [ent];] - note, changed the method to setEmail to match the documentation here. The error I get with this is:

ERROR 2015-06-22 09:58:34,719 [main] org.mule.exception.DefaultMessagingExceptionStrategy: 
********************************************************************************
Message               : Object "org.mule.transport.NullPayload" not of correct type. It must be of type "{interface java.lang.Iterable,interface java.util.Iterator,interface org.mule.routing.MessageSequence,interface java.util.Collection}" (java.lang.IllegalArgumentException). Message payload is of type: NullPayload
Code                  : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. Object "org.mule.transport.NullPayload" not of correct type. It must be of type "{interface java.lang.Iterable,interface java.util.Iterator,interface org.mule.routing.MessageSequence,interface java.util.Collection}" (java.lang.IllegalArgumentException)
  org.mule.util.collection.EventToMessageSequenceSplittingStrategy:64 (null)
2. Object "org.mule.transport.NullPayload" not of correct type. It must be of type "{interface java.lang.Iterable,interface java.util.Iterator,interface org.mule.routing.MessageSequence,interface java.util.Collection}" (java.lang.IllegalArgumentException). Message payload is of type: NullPayload (org.mule.api.MessagingException)
  org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:32 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
java.lang.IllegalArgumentException: Object "org.mule.transport.NullPayload" not of correct type. It must be of type "{interface java.lang.Iterable,interface java.util.Iterator,interface org.mule.routing.MessageSequence,interface java.util.Collection}"
    at org.mule.util.collection.EventToMessageSequenceSplittingStrategy.split(EventToMessageSequenceSplittingStrategy.java:64)
    at org.mule.util.collection.EventToMessageSequenceSplittingStrategy.split(EventToMessageSequenceSplittingStrategy.java:25)
    at org.mule.routing.CollectionSplitter.splitMessageIntoSequence(CollectionSplitter.java:29)
    + 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
1

There are 1 answers

4
Ryan Carter On BEST ANSWER

One way is to build up the object yourself using the constructor or properties/setters.

From the docs: http://mulesoft.github.io/magento-connector/2.1.2/java/com/magento/api/CustomerCustomerEntity.html

<mock:then-return payload-ref="#[ent = new com.magento.api.CustomerCustomerEntity(); ent.email('[email protected]'); return ent;]"/>

You can also create these objects aS reusable spring beans and reference them from MEL.

    <bean class="com.magento.api.CustomerCustomerEntity" id="myEntityWithEmail">
            <property name="email" value="[email protected]" />
    </bean>

    <mock:then-return payload-ref="#[app.registry.myEntityWithEmail]"/>

After your update I can see that you sre using a foreach which expects a collection or iterable. YOu can return a collection of you custom object simply in MEL using: [] for example:

#[ent = new com.magento.api.CustomerCustomerEntity(); ent.email('[email protected]'); return [ent];]

More on MEL here: https://developer.mulesoft.com/docs/display/current/Mule+Expression+Language+MEL

Or again you can use Spring to return a list:

<util:list id="entities">
    <ref bean="myEntityWithEmail" />
</util:list>