エラーのテストとモック

テストでのエラーの想定

フローの実行中にコンポーネントで、テスト中のユースケースで想定されるエラーがスローされることがあります。このような場合、テストで特定のエラー種別や例外が想定されていることを指定します。

たとえば、次の Mule コードを見てみましょう。

<flow name="retrieveKey">
    <os:retrieve key="#[payload.key]"/>
    <set-variable value="#[payload.id]" variableName="userId"/>
</flow>

キーはペイロードから取得され、キーが ​null​ の場合、Object Store Connector で ​OS:INVALID_KEY​ エラー種別のエラーがスローされます。

このケースを検証するテストは次のようになります。

<munit:test name="retrieveNullKeyTest" description="Expect error when key is null" expectedErrorType="OS:INVALID_KEY">
    <munit:behavior>
        <munit:set-event>
            <munit:payload value="#[ { key: null}]" />
        </munit:set-event>
    </munit:behavior>
    <munit:execution>
        <flow-ref name="retrieveKey"/>
    </munit:execution>
</munit:test>

エラーハンドラーのテスト

通常、エラーはユーザーによって処理されます。ユーザーは、エラーがスローされたときに何らかのアクションを実行したり、エラーを伝播するのか、フローの実行を続行するのかを決定したりできます。

次の可能性ごとに異なるテストを実行できます。

On Error Continue

たとえば、次の Mule コードを見てみましょう。

<flow name="retrieveKey">
    <os:retrieve key="#[payload.key]"/>
    <set-variable value="#[payload.id]" variableName="userId"/>
    <error-handler >
        <on-error-continue type="OS:INVALID_KEY">
            <set-payload value="#[{ message : 'Key is null'}]" />
        </on-error-continue>
    </error-handler>
</flow>

OS:INVALID_KEY​ エラーは処理され、特定のペイロードを使用して実行が続行されます。

エラーは伝播されないため、実行が再開されてイベントを検証できます。

<munit:test name="retrieveNullKeyTest" description="Expect message when key is null">
    <munit:behavior>
        <munit:set-event>
            <munit:payload value="#[ { key: null}]" />
        </munit:set-event>
    </munit:behavior>
    <munit:execution>
        <flow-ref name="retrieveKey"/>
    </munit:execution>
    <munit:validation >
        <munit-tools:assert-that expression="#[payload.message]" is="#[MunitTools::equalTo('Key is null')]"/>
    </munit:validation>
</munit:test>

ご覧のとおり、このケースでは、​OS:INVALID_KEY​ エラー種別を想定する必要はありません。

On Error Propagate

たとえば、ユーザーのコードが次のようになっている場合、

<flow name="retrieveKey">
    <os:retrieve key="#[payload.key]"/>
    <set-variable value="#[payload.id]" variableName="userId"/>
    <error-handler >
        <on-error-propagate type="OS:INVALID_KEY">
            <raise-error type="APP:NULL_KEY"/>
        </on-error-propagate>
    </error-handler>
</flow>

OS:INVALID_KEY​ エラーが処理され、エラー ​APP:NULL_KEY​ が発生します。

発生したカスタムエラー種別でテストが失敗するため、テストでこれを想定しておく必要があります。

<munit:test name="retrieveNullKeyTest" description="Expect APP:NULL_KEY is raised" expectedErrorType="APP:NULL_KEY">
    <munit:behavior>
        <munit:set-event>
            <munit:payload value="#[ { key: null}]" />
        </munit:set-event>
    </munit:behavior>
    <munit:execution>
        <flow-ref name="retrieveKey"/>
    </munit:execution>
</munit:test>

モックエラー

(上記の例のように) コンポーネントのエラーを手動でトリガーしないが、特定のエラーでプロセッサーを失敗させる場合、mock-when プロセッサーの ​error​ パラメーターを使用できます。

たとえば、ユーザーのコードが次のようになっている場合、

<flow name="requestFlow">
    <http:request method="GET" config-ref="HTTP_Request_configuration"/>
    <set-variable value="#[payload.id]" variableName="userId"/>
    <error-handler >
        <on-error-continue type="HTTP:CONNECTIVITY">
            <logger level="ERROR" message="AN ERROR OCCURRED"/>
        </on-error-continue>
    </error-handler>
</flow>

HTTP:CONNECTIVITY​ エラーで ​http:request​ を失敗させ、ロガーが実際に実行されたかどうかを確認するテストは次のようになります。

On Error Continue でのモックエラー
<munit:test name="requestFlowTest" description="Mock CONNECTIVITY error" >
    <munit:behavior >
        <munit-tools:mock-when processor="http:request">
            <munit-tools:then-return >
                <munit-tools:error typeId="HTTP:CONNECTIVITY" />
            </munit-tools:then-return>
        </munit-tools:mock-when>
    </munit:behavior>
    <munit:execution >
        <flow-ref name="requestFlow"/>
    </munit:execution>
    <munit:validation >
        <munit-tools:verify-call processor="mule:logger"/>
    </munit:validation>
</munit:test>

On Error スコープが ​on-error-propagate​ の場合、フローはエラーを伝播して失敗するため、検証が実行されません。そのため、テストの ​validation​ セクションはスキップされます。

この場合、エラーを try スコープでキャッチすれば、検証を実行できます。

On Error Propagate でのモックエラー
<munit:test name="requestFlowTest" description="Mock CONNECTIVITY error" >
    <munit:behavior >
        <munit-tools:mock-when processor="http:request">
            <munit-tools:then-return >
                <munit-tools:error typeId="HTTP:CONNECTIVITY" />
            </munit-tools:then-return>
        </munit-tools:mock-when>
    </munit:behavior>
    <munit:execution >
        <try>
            <flow-ref name="requestFlow"/>
            <error-handler >
                <on-error-continue type="HTTP:CONNECTIVITY"/>
            </error-handler>
        </try>
    </munit:execution>
    <munit:validation >
        <munit-tools:verify-call processor="mule:logger"/>
    </munit:validation>
</munit:test>

エラーのあるイベントの設定

エラー処理ロジックを別々のフローまたはサブフローに抽出する場合、入力イベントにエラー処理ロジックで使用できるエラーが含まれている必要があります。

たとえば、次の Mule コードを見てみましょう。

<flow name="retrieveFlow">
    <os:retrieve key="#[payload.key]"/>
    <error-handler >
        <on-error-continue>
            <flow-ref name="error-handlingSub_Flow"/>
        </on-error-continue>
    </error-handler>
</flow>

<sub-flow name="error-handlingSub_Flow">
    <logger level="INFO" message="#['Execution failed with: $(error.description)']"/>
</sub-flow>

個別にサブフローをテストするには、イベントでエラーを設定する必要があります。

テストは次のようになります。

イベントのエラーの設定
<munit:test name="error_handlingSub_FlowTest" description="Test subFlow" >
    <munit:behavior >
        <munit:set-event>
            <munit:error id="OS:INVALID_KEY" exception="#[java!java::lang::Exception::new('Invalid Key')]"/>
        </munit:set-event>
    </munit:behavior>
    <munit:execution >
        <flow-ref name="error-handlingSub_Flow"/>
    </munit:execution>
    <munit:validation >
        <munit-tools:verify-call processor="mule:logger">
            <munit-tools:with-attributes >
                <munit-tools:with-attribute attributeName="message" whereValue="#['Execution failed with: Invalid Key']" />
            </munit-tools:with-attributes>
        </munit-tools:verify-call>
    </munit:validation>
</munit:test>