Search code examples
javabddcitrus-framework

Reuse HTTP message in different methods in Citrus Framework


Problem: How to reuse the same HTTP message in two different methods (in the same step) in Citrus Framework

Versions: Citrus 2.8.0-SNAPSHOT; Cucumber 3.0.2; Java 8

Having this Gherkin:

    Scenario: Client has permission to access the action
        Given that client has access to action
        When the client calls the endpoint /some-endpoint/client/1/action/some-action
        Then the client receives status code of 200
        And the client receives a response with {"action" : "some-action", "permission": "AUTHORIZED"}

and the following piece of Java code:

  @Then("the client receives status code of {int}")
  public void the_client_receives_status_code_of(Integer statusCode) {

    designer.http().client(httpClient).receive().response(HttpStatus.valueOf(statusCode))
        .contentType("application/json;charset=UTF-8"):
  }

  @Then("the client receives a response with {string}")
  public void the_client_receives_a_response_with(String payload) {

    designer.http().client(httpClient).receive().response().payload(payload);
  }

If this code is run, it will give a timeout in the method the_client_receives_a_response_with, since Citrus is expecting to receive a second message (send method was only called once).

The objective here is to separate the validations of the HTTP code from the payload, so the separation was made by creating two methods. How to reuse the message received in method the_client_receives_status_code_of?

Already tried the following without success:

Giving a name to the received message:

designer.http().client(httpClient).receive().response(HttpStatus.valueOf(statusCode)).name("currentMessage")
        .contentType("application/json;charset=UTF-8");

But trying to access the message like this:

@CitrusResource
private TestContext testContext;
...
testContext.getMessageStore().getMessage("currentMessage");

Returns null.

But using this:

designer.echo("citrus:message(currentMessage)");

Prints the correct message.

So, how can I access the message in Java code, i.e, have access to the message to do something like this:

Assert.assertTrue(testContext.getMessageStore().getMessage("currentMessage").getPayload().equals(payload));

In two different methods.


Solution

  • You can do something like this:

    @Then("the client receives a response with {string}")
    public void the_client_receives_a_response_with(String payload) {
        designer.action(new AbstractTestAction() {
            public void doExecute(TestContext context) {
                Assert.assertTrue(context.getMessageStore()
                                             .getMessage("currentMessage")
                                             .getPayload(String.class)
                                             .equals(payload));
            }
        });
    }
    

    The abstract action is always provided with the current TestContext instance of your running test. So the @CitrusResource injection is not working here as you get a different instance where the named message is unknown.

    Also as an alternative you could follow the default named messages steps BDD API that is described here: https://citrusframework.org/citrus/reference/html/index.html#named-messages

    Maybe message creator BDD API will also help: https://citrusframework.org/citrus/reference/html/index.html#message-creator-steps