muleanypoint-studiomunitmulesoft

Munit 4: Is there a way to mock a payload from the same cache-scoped HTTP Request in different test cases for a suite?


I am trying to Mock a response payload from HTTP request like this:

        <munit-tools:mock-when doc:name="doc-name"
            doc:id="doc-id" processor="http:request">
            <munit-tools:with-attributes>
                <munit-tools:with-attribute
                    attributeName="doc:name" whereValue="#['DOCNAME']" />
            </munit-tools:with-attributes>
            <munit-tools:then-return>
                <munit-tools:payload mediaType="application/json"
                    value="#[MunitTools::getResourceAsString('testPayloadA.json')]" />
            </munit-tools:then-return>
        </munit-tools:mock-when>

Then in another test case, I mock the same HTTP request like this:

        <munit-tools:mock-when doc:name="doc-name"
            doc:id="doc-id" processor="http:request">
            <munit-tools:with-attributes>
                <munit-tools:with-attribute
                    attributeName="doc:name" whereValue="#['DOCNAME']" />
            </munit-tools:with-attributes>
            <munit-tools:then-return>
                <munit-tools:payload mediaType="application/json"
                    value="#[MunitTools::getResourceAsString('testPayloadB.json')]" />
            </munit-tools:then-return>
        </munit-tools:mock-when>

Basically the mock has the same structure for at least 4 cases where I am trying to evaluate the behavior that varies depending on the content of the payload that comes from the Http Request with name DOCNAME. The fact is that this request is enclosed in a Cache scope. This means that if I try to run the test cases individually, they will do it successfully, but when all the suite is run, the first case executes OK but the subsequent ones fail.

Does anyone have an idea about how a response payload from a cache-scoped request should be mocked in a way that does not affect all the test suite?


Solution

  • So im guessing the tests are failing because the previous value is cached. This could be down to the caching strategy and maybe using different data per test so the cache always misses.

    But in case you need to use similar data, you can clear the cache before each test. For example:

    Given this flow, setup a named object store and caching strategy that uses said object store:

    <os:object-store name="myObjectStore" doc:name="Object store"
            doc:id="25cec35b-2680-4754-8073-633f3e60a34f" />
        <ee:object-store-caching-strategy
            name="Caching_Strategy" objectStore="myObjectStore" doc:name="Caching Strategy"
            doc:id="fd059f4f-d3be-4971-a36c-374506e2db49" />
    
        <flow name="httpCache">
            <ee:cache cachingStrategy-ref="Caching_Strategy"  doc:name="Cache"  doc:id="0dcabdb4-d6fc-41d5-aebd-77d015e02dd7" >
                <http:request method="GET" doc:name="Request" doc:id="366184e9-6c0b-41d4-8414-3dfdd047ecb2" url="http://google.com"/>
                <logger level="ERROR" message="CACHE MISS" />
            </ee:cache>
            <logger level="ERROR" message="After cache: #[payload]" />   
        </flow>
    

    Then is your tests, setup a before action to clear that store:

    <munit:before-test name="clearOS" description="clears OS">
                <os:clear objectStore="myObjectStore" doc:id="cd931ce7-6945-4dc9-919a-3ff9b158d746" />
        </munit:before-test>
    
        <munit:test name="new-test-suite-httpCacheTest" description="Test" doc:id="b8e299ea-d191-4c0a-ac71-27a12b28d275" >
            <munit:behavior >
                <munit-tools:mock-when doc:name="Mock when" doc:id="8bf1468d-c9c1-48a1-9009-bae02bf8e788" processor="http:request">
                    <munit-tools:with-attributes >
                        <munit-tools:with-attribute attributeName="doc:name" whereValue="Request" />
                    </munit-tools:with-attributes>
                    <munit-tools:then-return >  
                         <munit-tools:payload value="#['mockPayload']"/>
                    </munit-tools:then-return>
                </munit-tools:mock-when>
            </munit:behavior>
            <munit:execution >
                <flow-ref doc:name="Flow-ref to httpCache" doc:id="2dd44c7b-f250-4852-9e53-f4eee3b5ad84" name="httpCache"/>
            </munit:execution>
            <munit:validation >
                <munit-tools:assert-that doc:name="Assert that" doc:id="6521459d-04dd-4e59-8a2e-16a27f51c091" expression="#[payload]" is="#[MunitTools::notNullValue()]"/>
            </munit:validation>
        </munit:test>
    
        <munit:test name="new-test-suite-httpCacheTest2" description="Test" doc:id="d6ea0d83-f943-450e-948c-26596bf41207" >
            <munit:behavior >
                <munit-tools:mock-when doc:name="Mock when" doc:id="8688876f-144e-4f7f-8ef0-98a8e6caeca0" processor="http:request">
                    <munit-tools:with-attributes >
                        <munit-tools:with-attribute attributeName="doc:name" whereValue="Request" />
                    </munit-tools:with-attributes>
                    <munit-tools:then-return >  
                         <munit-tools:payload value="#['mockPayload2']"/>
                    </munit-tools:then-return>
                </munit-tools:mock-when>
            </munit:behavior>
            <munit:execution >
                <flow-ref doc:name="Flow-ref to httpCache" doc:id="b4a1d37a-f0e4-4fa1-9c78-084ed3f6faf8" name="httpCache"/>
            </munit:execution>
            <munit:validation >
                <munit-tools:assert-that doc:name="Assert that" doc:id="46febad5-d557-4152-829e-db61aa6ef409" expression="#[payload]" is="#[MunitTools::notNullValue()]"/>
            </munit:validation>
        </munit:test>
    

    Both of these will log:

    LoggerMessageProcessor: CACHE MISS
    

    And then:

    LoggerMessageProcessor: After cache: mockPayload
    
    LoggerMessageProcessor: After cache: mockPayload2
    

    Where as, without the os:clear it would only miss the cache first time, and print out the same payload from the cache:

     LoggerMessageProcessor: CACHE MISS
     LoggerMessageProcessor: After cache: mockPayload
    
     LoggerMessageProcessor: After cache: mockPayload
    

    Or alternatively, you could move the cache and http processors to their own flow and mock the flow instead so cache is never used in your tests.