# Using MockServer as an arbitrary JSON matcher

When writing integration tests, have you ever needed to match a JSON object against a specific pattern? I did, recently. The solution I found was an elegant hack (isn’t that an oximoron?) using the excellent [MockServer](https://www.mock-server.com/). Let's explore how this hack works and why I chose this solution.

I was writing an integration test for one of the Walletera services, the [payments](https://github.com/walletera/payments) service. What I wanted to verify in the test was this:

```plaintext
When a payment is created
Then the payments service publishes the following event: ...
```

In Walletera, the events are JSON objects, so I needed a way to verify that a JSON object conforms with a certain structure. This wasn't an exact comparison because some parts are dynamic, like current timestamps, JWT tokens, UUIDs, etc. So, I needed a JSON matcher. Naturally, my first step was to search for "golang json matcher" online. After reviewing the results, the most promising Go package that I found was [https://github.com/panta/go-json-matcher](https://github.com/panta/go-json-matcher). I decided to try it out. It works, but there's a drawback. It only tells you if the JSON matched the specification or not, without providing any additional information about why the JSON didn't match. For simple JSON objects, this solution might be sufficient, but for more complex cases, it falls short.

So, I need a JSON matcher that allows me to match JSON objects with dynamic elements and also, in the case of a mismatch, tells me where the difference is between the actual JSON object and the expected JSON structure.

I was already using in my integration tests a component that satisfied almost all my needs, the great [MockServer](https://www.mock-server.com/). It has an excellent [JSON matcher](https://www.mock-server.com/mock_server/creating_expectations.html#button_match_request_by_body_with_json_exactly), and in the case of a mismatch, you can check the logs to see exactly why the match failed. The only problem was that MockServer verifies HTTP requests, not random JSON objects. After thinking a bit I said, fuck it, let’s embeded our event JSON into an HTTP request. It is slower than using a matching library, but in the context of an integration test, this is negligible.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">If you are interested in how to write integration tests in Go, following BDD style and, of course, using MockServer, check the previous article from this blog: <a target="_self" rel="noopener noreferrer nofollow" href="https://walletera.dev/using-bdd-to-implement-a-payments-gateway-part-2" style="pointer-events: none">using-bdd-to-implement-a-payments-gateway-part-2</a>. You can also navigate the <a target="_self" rel="noopener noreferrer nofollow" href="https://github.com/orgs/walletera/repositories" style="pointer-events: none">walletera repositories in Github</a>, where you will find plenty of integration tests examples.</div>
</div>

Now, let’s see how we can build a generic JSON matcher using MockServer. It’s very simple, we just need to create a generic MockServer [expectation](https://www.mock-server.com/mock_server/creating_expectations.html). The HTTP method and path could be whatever you like. I choose `POST` as the method and `/matchevent` as the path.

```go
    httpRequestExpectationWrapperTemplate := `
    {
      "id": "%s",
      "httpRequest" : {
        "method": "POST",
        "path": "/matchevent",
        "body": {
            "type": "JSON",
            "json": %s,
            "matchType": "ONLY_MATCHING_FIELDS"
        }
      },
      "httpResponse" : {
        "statusCode" : 201,
        "headers" : {
          "content-type" : [ "application/json" ]
        }
      },
      "priority" : 0,
      "timeToLive" : {
        "unlimited" : true
      },
      "times" : {
        "unlimited" : true
      }
    }
`
```

Note the placeholders `%s` in the string. This string is a template; we can instantiate it with an expectation id and a JSON matcher like this:

```go
httpRequestExpectationWrapper := fmt.Sprintf(httpRequestExpectationWrapperTemplate, expectationId, eventMatcher)
```

The `expectationId` will be used later to ask MockServer if the expectation was or was not met. The `eventMatcher` is a JSON object with optional placeholders to match objects with dynamic fields. Let's see an example matcher.

```json
    {
      "id": "${json-unit.regex}^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$",
      "type": "PaymentCreated",
      "data": {
        "id": "${json-unit.regex}^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$",
        "amount": 100,
        "currency": "ARS",
        "direction": "inbound",
        "customerId": "${json-unit.regex}^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$",
        "status": "pending",
        "beneficiary": {
          "bankName": "dinopay",
          "bankId": "dinopay",
          "accountHolder": "John Doe",
          "routingKey": "123456789123456"
        },
        "createdAt": "${json-unit.any-string}"
      }
    }
```

For more info on the supported options for the JSON matcher, check the MockServer [documentation](https://www.mock-server.com/mock_server/creating_expectations.html#button_match_request_by_body_with_json_exactly).

Now, the best part is that if the match fails, you check the MockServer logs, which looks like this

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1743533415153/76231e22-a6ea-45b9-b07c-ed6411fc674f.jpeg align="center")

The output tells you the exact field (or fields) that didn’t match (in this case `data.direction`), the expected value, and the provided value.

And that’s it, we built a generic and powerful JSON matcher using MockServer. I hope you find this hack useful. See you at the next stop of the Walletera journey.
