Skip to content

Mock Parallel Third Party Server Communication #1350

@coosmic

Description

@coosmic

Citrus Version
4.5.2 ( can be reproduced with 4.6 as well)

Question
How can I mock parallel server communication with third party system?

Use Case:
Citrus client calls SUT which calls third party system. Now I want to do the same but in parallel. Two parallel client requests are sufficient. For client requests I know I need to use a selector in the response (example from docs works great without mocking the server communication using citrus_message_id), but how can I do the same for server request and response mocking?

What I've tried so far

  1. Use parallel container with sequential block (closest to what I could find in the docs and what I actually like to do)
runner.run(parallel()
                       .actions(
                           sequential().actions(
                               createForkedRequest(httpClient, "ClientA"),
                               mockThirdPartyServerRequest(),mockThirdPartyServerResponse(),
                               createResponse(httpClient, "ClientA")),
                           sequential().actions(
                               createForkedRequest(httpClient, "ClientB"),
                               mockThirdPartyServerRequest(),mockThirdPartyServerResponse(),
                               createResponse(httpClient, "ClientB"))
                       ));

This will run into "Failed to find reply channel for message correlation key: citrus_message_id = 'ffce4ac3-4f4e-47a4-a755-541deea1cff0'" error.
2. Use parallel container only for client request and response mocking (separate parallel containers), while server communication is mocked in a sequential container in between (this works, but doesn't cover my goal)

runner.run(parallel()
                       .actions(
                           createForkedRequest(httpClient, "ClientA"),
                           createForkedRequest(httpClient, "ClientB")
                       ));

        runner.run(sequential().actions(mockThirdPartyServerRequest(),mockThirdPartyServerResponse(),
                                        mockThirdPartyServerRequest(),mockThirdPartyServerResponse()));

        runner.run(parallel()
                       .actions(
                           createResponse(httpClient, "ClientA"),
                           createResponse(httpClient, "ClientB")
                       ));
  1. Use 3 parallel container one for client request one for server communication one for client response (just to be on the save side, that client and s)
runner.run(parallel()
                       .actions(
                           createForkedRequest(httpClient, "ClientA"),
                           createForkedRequest(httpClient, "ClientB")
                       ));

        runner.run(parallel().actions(mockThirdPartyServerRequest(),mockThirdPartyServerResponse(),
                                        mockThirdPartyServerRequest(),mockThirdPartyServerResponse()));

        runner.run(parallel()
                       .actions(
                           createResponse(httpClient, "ClientA"),
                           createResponse(httpClient, "ClientB")
                       ));

Additional information
My overarching goal is to manipulate the third party requests and test how my SUT behaves under different scenarios, so running the 3rd party requests in sequential order is not an option.
e.g: SUT creates an entity in DB and locks it when a specific endpoint is called. While SUT holds the lock it will do some 3rd party communication which I need to delay so that the second request can run into the lock error reliable.

I added an Example Project containing a server which does a simple request on the only endpoint and junit test suite to demonstrate what I tried.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions