Asynchronous steps execution with Cucumber (and/or Citrus)

1.9k views Asked by At

Suppose I have a test like below (using cucumber) -

Scenario: Login successfully to Facebook
  Given the user test exists
  And user name and password is entered
  When the login form is submitted
  Then I expose a HTTP-Rest service to validate the user name and password
  When I receive a validation success message
  Then display the welcome message to the user

Here, when "the login form is submitted" is called, it submit the request to a HTTP REST service which will pass the user name and password to another HTTP Rest Service (that would be exposed by Citrus Framework) using "I expose a HTTP-Rest service to validate the user name and password" which will validate the data and send a success response. Therefore step definitions for "the login form is submitted" and "I expose a HTTP-Rest service to validate the user name and password" should be executed asynchronously.

Could you please help me - how I could achieve this using cucumber (or/and citrus).

Note: I'm not using any stub application to expose the HTTP Rest service for "I expose a HTTP-Rest service to validate the user name and password"; I'm trying to expose the service using Citrus framework.

Step definitions are written in java.

1

There are 1 answers

0
Christoph Deppisch On BEST ANSWER

First of all you need to setup the citrus-cucumber extension in your project. Then you should be able to use @CitrusResource annotation that injects a test runner instance to your steps class:

@CitrusResource
private TestRunner runner;

Also you can inject the http server instance that should receive the request.

@CitrusEndpoint(name = "userServer")
private HttpServer userServer;

Then you can use test runner and the server to receive the request and send the response in a step definition:

@Then("^I expose a HTTP-Rest service to validate the user name and password$")
public void exposeHttpRestService() {
    runner.http(http -> http.server(userServer)
        .receive()
        .post()
        .payload("{\"username\": \"test\", \"password\": \"secret\"}"));

    runner.http(http -> http.server(userServer)
        .send()
        .response(HttpStatus.OK));
}

The login form should be submitted in a separate step definition using a separate thread in order to create asynchronous nature:

@When("^the login form is submitted$")
public void submitForm() {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.submit(() -> {
        // do submit the form
    });    
}