Skip to content

Steps When

Jörg Flade edited this page Jun 24, 2026 · 3 revisions

When — REST Calls

URL paths can be shortened by setting a base path with Given — Request Setup before the When step.

HTTP Methods

All {httpMethod} steps accept the following values in place of {httpMethod}:

GET   POST   PUT   PATCH   DELETE

The following examples use GET or POST, but any of the five methods works in the same position.


Previously given URI and body

When executing a {httpMethod} call with previously given URI and body
When executing an authorized {httpMethod} call with previously given URI and body

Executes a request using a URI and body that were both set in preceding Given steps. The authorized variant sends a Bearer token in the Authorization header; the plain variant does not.

Requires:

Scenario: Create a user (authorized)
  Given that all file paths are relative to "features/users"
  And that the API path is "/api/v1/users"
  And that the file "request/create_user.json" is used as the body
  When executing an authorized POST call with previously given URI and body
  Then I ensure that the status code of the response is 201

Scenario: Create a resource (no auth)
  Given that the API path is "/api/v1/public/resources"
  And that the body of the request is
    """
    { "name": "My Public Resource" }
    """
  When executing a POST call with previously given URI and body
  Then I ensure that the status code of the response is 201

URL with previously given body

When executing a {httpMethod} call to {string} with previously given body
When executing an authorized {httpMethod} call to {string} with previously given body

Calls the URL given directly in the sentence, using a body set in a preceding Given step. Simpler than the previous variant when no URI manipulation is needed.

The token used depends on Define That a Token Without Scopes Should Be Used.

Requires: Set a Body from JSON File for Later Execution or Set a Body Directly for Later Execution

Scenario: Update a user
  Given that the body of the request is
    """
    {
      "firstName": "John",
      "lastName":  "Doe"
    }
    """
  When executing an authorized PUT call to "/api/v1/users/123" with previously given body
  Then I ensure that the status code of the response is 200

Scenario: Update using a file body
  Given that all file paths are relative to "features/users"
  And that the file "request/update_user.json" is used as the body
  When executing an authorized PATCH call to "/api/v1/users/123" with previously given body
  Then I ensure that the status code of the response is 200

URL with body from file

When executing a {httpMethod} call to {string} with the body from file {string}
When executing an authorized {httpMethod} call to {string} with the body from file {string}

Reads the request body from the given file and calls the URL given inline in the sentence. The file path respects the base file path set with Set Base Path for Files.

Scenario: Create a user from file (authorized)
  Given that all file paths are relative to "features/users"
  When executing an authorized POST call to "/api/v1/users" with the body from file "request/create_user.json"
  Then I ensure that the status code of the response is 201

Scenario: Submit public data from file (no auth)
  When executing a POST call to "/api/v1/public/submit" with the body from file "absolutePath:shared/request/submit.json"
  Then I ensure that the status code of the response is 200

The absolutePath: prefix resolves the file from the classpath root, ignoring any base file path set earlier.


Previously given URI only (no body)

When executing a {httpMethod} call with previously given URI
When executing an authorized {httpMethod} call with previously given URI

Calls the URI set by Given that the API path is {string}, without a request body. Useful for GET and DELETE where URI manipulation (e.g. dynamic elements) is needed before execution.

Requires: Set a URI Path for Later Execution

Scenario: Delete a resource
  Given that the API path is "/api/v1/users/123"
  When executing an authorized DELETE call with previously given URI
  Then I ensure that the status code of the response is 204

Scenario: Fetch a resource (no auth)
  Given that the API path is "/api/v1/public/status"
  When executing a GET call with previously given URI
  Then I ensure that the status code of the response is 200

Direct URL (no body)

When executing a {httpMethod} call to {string}
When executing an authorized {httpMethod} call to {string}

The simplest form — URL inline, no body, no prior setup required. The authorized variant sends a Bearer token; the plain variant does not.

The token used depends on Define That a Token Without Scopes Should Be Used.

Scenario: Fetch a list of users
  When executing an authorized GET call to "/api/v1/users"
  Then I ensure that the status code of the response is 200

Scenario: Delete a resource
  When executing an authorized DELETE call to "/api/v1/users/123"
  Then I ensure that the status code of the response is 204

Scenario: Access a public endpoint
  When executing a GET call to "/api/v1/health"
  Then I ensure that the status code of the response is 200

Combine with a URL base path to keep the endpoint short:

Feature: Users API

  Background:
    Given that all URLs are relative to "/api/v1/users"

  Scenario: Fetch all users
    When executing an authorized GET call to ""
    Then I ensure that the status code of the response is 200

  Scenario: Fetch a specific user
    When executing an authorized GET call to "/123"
    Then I ensure that the status code of the response is 200

Dynamic URI elements

Use these steps when part of the URL is a placeholder that must be filled from a data table at runtime. The API path must be set as a template using {placeholderName} syntax.

With previously given body:

When executing a {httpMethod} call with previously given API path, body and these dynamic 'URI Elements' replaced with the 'URI Values'
  | URI Elements  | URI Values |
  | resourceId    | abc-def-gh |
  | subResourceId | xyz-456    |

When executing an authorized {httpMethod} call with previously given API path, body and these dynamic 'URI Elements' replaced with the 'URI Values'
  | URI Elements  | URI Values |
  | resourceId    | abc-def-gh |
  | subResourceId | xyz-456    |

Without body:

When executing a {httpMethod} call with previously given API path and these dynamic 'URI Elements' replaced with the 'URI Values'
  | URI Elements  | URI Values |
  | resourceId    | abc-def-gh |

When executing an authorized {httpMethod} call with previously given API path and these dynamic 'URI Elements' replaced with the 'URI Values'
  | URI Elements  | URI Values |
  | resourceId    | abc-def-gh |

The URI Values column is first looked up in ScenarioContext. If a matching key is found, the stored value is used; otherwise the literal table value is used.

Requires (body variant): Set a URI Path for Later Execution and Set a Body from JSON File for Later Execution

Requires (no-body variant): Set a URI Path for Later Execution

Scenario: Update a sub-resource (body from file + dynamic URI)
  Given that all file paths are relative to "features/orders"
  And that the API path is "/api/v1/orders/{orderId}/items/{itemId}"
  And that the file "request/update_item.json" is used as the body
  When executing an authorized PUT call with previously given API path, body and these dynamic 'URI Elements' replaced with the 'URI Values'
    | URI Elements | URI Values |
    | orderId      | order-123  |
    | itemId       | item-456   |
  Then I ensure that the status code of the response is 200

Scenario: Delete a sub-resource (no body, dynamic URI)
  Given that the API path is "/api/v1/orders/{orderId}/items/{itemId}"
  When executing an authorized DELETE call with previously given API path and these dynamic 'URI Elements' replaced with the 'URI Values'
    | URI Elements | URI Values     |
    | orderId      | STORED_ORDER   |
    | itemId       | STORED_ITEM    |
  Then I ensure that the status code of the response is 204

In the second example, STORED_ORDER and STORED_ITEM are keys in ScenarioContext set by a previous Then — Context step.

Using ScenarioContext to pass data between scenarios is an Anti-Pattern. Use with deliberate intent, primarily in end-to-end test flows.


Form-data POST

For multipart/form-data requests with optional file attachment.

Step 1 — store the file to attach (optional):

Given that the file {string} is stored as "FORM_FILE"

Step 2 — execute the form-data request:

When executing a form-data POST call to {string} with the fields
  | text-field-key | text-field-value |

When executing an authorized form-data POST call to {string} with the fields
  | text-field-key | text-field-value |

The text fields are a key/value data table. The file stored as FORM_FILE is attached automatically if set.

Scenario: Upload a document with metadata (authorized)
  Given that the file "test-document.pdf" is stored as "FORM_FILE"
  When executing an authorized form-data POST call to "/api/v1/documents" with the fields
    | description | Quarterly report |
    | category    | finance          |
  Then I ensure that the status code of the response is 201

Scenario: Submit a form without a file attachment
  When executing a form-data POST call to "/api/v1/contact" with the fields
    | name    | Jane Doe          |
    | email   | jane@example.com  |
    | message | Hello!            |
  Then I ensure that the status code of the response is 200

Examples: bdd-cucumber-gherkin-lib/src/test/resources/features/form_data/


Polling

See When — Polling for steps that repeatedly call an endpoint until an expected status code or response body is received.

Clone this wiki locally