PHPackages                             auto1-oss/php-behat-context-wiremock - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. auto1-oss/php-behat-context-wiremock

ActiveLibrary[Testing &amp; Quality](/categories/testing)

auto1-oss/php-behat-context-wiremock
====================================

Behat context for Wiremock support

v1.1.1(7mo ago)25.3k↓39.1%2[1 PRs](https://github.com/auto1-oss/php-behat-context-wiremock/pulls)Apache-2.0PHPPHP &gt;=8.0CI passing

Since Nov 19Pushed 7mo ago3 watchersCompare

[ Source](https://github.com/auto1-oss/php-behat-context-wiremock)[ Packagist](https://packagist.org/packages/auto1-oss/php-behat-context-wiremock)[ RSS](/packages/auto1-oss-php-behat-context-wiremock/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (4)Versions (8)Used By (0)

php-behat-context-wiremock
==========================

[](#php-behat-context-wiremock)

This package provides a seamless integration between Behat tests and Wiremock, offering a straightforward method for mocking HTTP requests. It acts as a conduit between Behat scenarios and a Wiremock instance, enabling the creation of HTTP request expectations and mock responses without sacrificing Wiremock's inherent flexibility.

Configuration Example
---------------------

[](#configuration-example)

Below is an example of how to configure the Wiremock context within your Behat setup:

```
- Auto1\BehatContext\Wiremock\WiremockContext:
      baseUrl: 'http://wiremock'
      stubsDirectory: '%paths.base%/features/stubs'
      cleanWiremockBeforeEachScenario: false # Optional, defaults to false
      allStubsMatchedAfterEachScenario: false # Optional, defaults to false
      stubsDirectoryIsFeatureDirectory: false # Optional, defaults to false
```

- `baseUrl`: The URL of your Wiremock instance.
- `stubsDirectory`: The base directory for Wiremock stubs. This cannot be specified if `stubsDirectoryIsFeatureDirectory` is enabled.
- `cleanWiremockBeforeEachScenario`: If true, Wiremock will be cleared before each scenario.
- `allStubsMatchedAfterEachScenario`: If true, ensures that all stubs are matched after each scenario.
- `stubsDirectoryIsFeatureDirectory`: If true, stubs will be sourced from the directory of a Behat feature file. This can only be enabled if `stubsDirectory` is not specified.
- Note: `stubsDirectory` and `stubsDirectoryIsFeatureDirectory` cannot be used simultaneously.

Docker Integration
------------------

[](#docker-integration)

For those running Behat within Docker, integrating a Wiremock container is straightforward. The following configuration ensures that your tests wait for Wiremock to be fully initialized before running:

```
  php-fpm:
    depends_on:
      wiremock:
        condition: service_healthy

  wiremock:
    image: wiremock/wiremock:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80/__admin/mappings"]
      interval: 10s
      timeout: 10s
      retries: 5
```

Context Steps
-------------

[](#context-steps)

### Defining Wiremock Stubs

[](#defining-wiremock-stubs)

- **Given wiremock stub**: This step allows you to define a Wiremock stub directly within your scenario.

    **Example**:

    ```
        Given wiremock stub:
        """
          {
            "request": {
              "method": "GET",
              "url": "/some/thing"
            },

            "response": {
              "status": 200,
              "body": "Hello, world!",
              "headers": {
                  "Content-Type": "text/plain"
              }
            }
          }
        ```

    ```
- **Given wiremock stubs from {file}**: This step loads stubs from a specified file or directory and sends them to Wiremock.

    **Example**:

    ```
        Given wiremock stubs from "dir/awesome-stub.json"
        And wiremock stubs from "dir2"
    ```
- **Given wiremock stubs from {file} should be called {count} times**: This step loads stubs from a specified file or directory, sends them to WireMock and also allows you to verify that the stub is called the specified number of times.

    **Example**:

    ```
        Given wiremock stubs from "dir/awesome-stub.json" should be called 2 times
        And wiremock stubs from "dir2" should be called 2 times
    ```
- **Given wiremock stubs from {file} should be called once**: This step loads stubs from a specified file or directory, sends them to WireMock and also allows you to verify that the stub is called once.

    **Example**:

    ```
        Given wiremock stubs from "dir/awesome-stub.json" should be called once
        And wiremock stubs from "dir2" should be called once
    ```
- **Given wiremock stubs from {file} should be called at least {count} times**: This step loads stubs from a specified file or directory, sends them to WireMock and also allows you to verify that the stub is called at least the specified number of times.

    **Example**:

    ```
        Given wiremock stubs from "dir/awesome-stub.json" should be called at least 2 times
        And wiremock stubs from "dir2" should be called at least 2 times
    ```
- **Given wiremock stubs from {file} should be called at most {count} times**: This step loads stubs from a specified file or directory, sends them to WireMock and also allows you to verify that the stub is not called more than the specified number of times.

    **Example**:

    ```
        Given wiremock stubs from "dir/awesome-stub.json" and should be called at most 2 times
        And wiremock stubs from "dir2" and should be called at most 2 times
    ```

### Managing Wiremock State

[](#managing-wiremock-state)

- **Given clean wiremock**: Resets Wiremock to its initial state.

    **Example**:

    ```
        Given clean wiremock
    ```

### Validating Stubs

[](#validating-stubs)

- **Then all stubs should be matched**: Ensures that all added stubs were matched at least once and fails if there were any unexpected (unmatched) calls to Wiremock.

    **Example**:

    ```
        Then all stubs should be matched
    ```

Placeholder Processors
----------------------

[](#placeholder-processors)

The package includes a powerful placeholder processing system that allows you to dynamically transform content when loading Wiremock stubs. This feature enables you to process data (from external files or generated dynamically) and inject the transformed content directly into your stub definitions.

### How Placeholder Processors Work

[](#how-placeholder-processors-work)

Placeholder processors use a special syntax within your stub files to reference external content and apply transformations:

```
%processor_name(arguments)%

```

- `processor_name`: The name of the processor to use
- `arguments`: Comma-separated arguments passed to the processor

The processor system automatically:

1. Parses the placeholder syntax from your stub files
2. Loads the referenced external files (if applicable)
3. Applies the specified transformation
4. Replaces the placeholder with the processed content

It's important to note that processors are not limited to just retrieving content from files. They can perform any type of manipulation and generate any content that will be injected into the stub. While the built-in processors work with files, custom processors can generate content dynamically without necessarily relying on external files as input.

The system also provides error handling for general processor operations:

- **Processor Not Found**: Throws `WiremockContextException` when referencing non-existent processors

### Configuration

[](#configuration)

To use placeholder processors, you need to configure them in your Behat context. WiremockContext expects to receive an array of processor instances:

```
- Auto1\BehatContext\Wiremock\WiremockContext:
      baseUrl: 'http://wiremock'
      stubsDirectory: '%paths.base%/features/stubs'
      placeholderProcessors:
        - '@Auto1\BehatContext\Wiremock\PlaceholderProcessorRegistry\PlaceholderProcessor\FlattenTextProcessor'
        - '@Auto1\BehatContext\Wiremock\PlaceholderProcessorRegistry\PlaceholderProcessor\JsonToUrlEncodedQueryStringProcessor'
```

Note that the `@` symbol indicates that these are service references. WiremockContext will receive the actual processor instances from your dependency injection container.

### Built-in Processors

[](#built-in-processors)

#### FlattenTextProcessor

[](#flattentextprocessor)

**Name**: `flatten_text`

**Purpose**: Flattens text by replacing all whitespace characters (spaces, tabs, newlines, etc.) with single spaces and trims leading/trailing whitespace.

**Syntax**: `%flatten_text(filename)%`

**Arguments**:

- `filename`: Path to the text file relative to the stubs directory

**Example**:

Given a file `data/multiline.txt`:

```
Hello
    World
        Test

```

And a stub file:

```
{
  "request": {
    "method": "POST",
    "url": "/api/data",
    "bodyPatterns": [
      {
        "equalTo": "%flatten_text('data/multiline.txt')%"
      }
    ]
  },
  "response": {
    "status": 200
  }
}
```

The placeholder will be replaced with: `"Hello World Test"`

**Error Handling**:

- **File Not Found**: Throws `WiremockContextException` when referenced text files don't exist
- **Invalid Arguments**: Throws `WiremockContextException` for incorrect argument types

#### JsonToUrlEncodedQueryStringProcessor

[](#jsontourlencodedquerystringprocessor)

**Name**: `json_to_url_encoded_query_string`

**Purpose**: Converts JSON data to URL-encoded query string format, with support for ignoring specific characters from encoding.

**Syntax**: `%json_to_url_encoded_query_string(filename, [ignored_characters])%`

**Arguments**:

- `filename`: Path to the JSON file relative to the stubs directory
- `ignored_characters`: Array of characters that should not be URL-encoded (optional). If not provided, an empty array will be used by default.

**Example 1 - Basic Usage**:

Given a file `data/params.json`:

```
{
  "name": "John Doe",
  "age": 30,
  "active": true
}
```

And a stub file:

```
{
  "request": {
    "method": "POST",
    "url": "/api/submit",
    "bodyPatterns": [
      {
        "equalTo": "%json_to_url_encoded_query_string('data/params.json')%"
      }
    ]
  },
  "response": {
    "status": 200
  }
}
```

The placeholder will be replaced with: `"name=John%20Doe&age=30&active=1"`

**Example 2 - With Ignored Characters**:

Given a file `data/url_params.json`:

```
{
  "callback_url": "https://example.com/callback?token=abc123",
  "email": "user@example.com"
}
```

And a stub file:

```
{
  "request": {
    "method": "POST",
    "url": "/api/webhook",
    "bodyPatterns": [
      {
        "equalTo": "%json_to_url_encoded_query_string('data/url_params.json', [':', '/', '?', '=', '@', '.'])%"
      }
    ]
  },
  "response": {
    "status": 200
  }
}
```

The placeholder will be replaced with: `"callback_url=https://example.com/callback?token=abc123&email=user@example.com"`

**Example 3 - Complex JSON with Nested Objects**:

Given a file `data/complex.json`:

```
{
  "user": {
    "name": "John",
    "preferences": ["email", "sms"]
  },
  "metadata": {
    "source": "api",
    "version": 2
  }
}
```

The processor will JSON-encode nested objects and arrays:

- Result: `"user=%7B%22name%22%3A%22John%22%2C%22preferences%22%3A%5B%22email%22%2C%22sms%22%5D%7D&metadata=%7B%22source%22%3A%22api%22%2C%22version%22%3A2%7D"`

**Error Handling**:

- **File Not Found**: Throws `WiremockContextException` when referenced JSON files don't exist
- **Invalid JSON**: Throws `WiremockContextException` for malformed JSON content

### Advanced Argument Parsing

[](#advanced-argument-parsing)

The placeholder parser supports sophisticated argument parsing including:

**Arrays**: Use square brackets to define arrays

```
%processor_name('file.txt', ['@', '.', ':'])%

```

**Associative Arrays**: Use `=>` syntax for key-value pairs

```
%processor_name('file.txt', ['key1' => 'value1', 'key2' => 'value2'])%

```

**Mixed Data Types**: Support for strings, integers, floats, booleans, and null

```
%processor_name('file.txt', [42, 3.14, true, false, null, 'string'])%

```

**Nested Arrays**: Support for multi-dimensional arrays

```
%processor_name('file.txt', [['nested', 'array'], ['another', 'nested']])%

```

### Creating Custom Processors

[](#creating-custom-processors)

You can create custom processors by implementing the `PlaceholderProcessorInterface`:

```
