Skip to content

Commit

Permalink
feat: implemented initial version of schema validation #195 (#196)
Browse files Browse the repository at this point in the history
* feat: implemented initial version of schema validation #195

* chore: tweaks after review #195

* doc: added a validation section in the docs #195

* doc: added a validation section in the docs #195
  • Loading branch information
Richard Ruiter committed Oct 25, 2022
1 parent 2cc267b commit f6f7601
Show file tree
Hide file tree
Showing 17 changed files with 1,189 additions and 260 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ Camouflage is a service virtualization tool inspired by [namshi/mockserver](http

📁 Comes with a file explorer UI that allows modification of mock files hosted remotely. 📁

✅ Validation of requests and responses using your OpenApi schema's. ✅

# Getting Started

1. Camouflage is an NPM package, therefore to install Camouflage, you'd need to install NodeJS (>v14) first, if you haven't already done so.
Expand Down Expand Up @@ -111,6 +113,11 @@ cache:
ttl_seconds: 300
injection:
enable: false
validation:
enable: true
schemas:
- type: OpenApi
url: https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json
origins:
- http://localhost:3000
- http://localhost:3001
Expand Down
5 changes: 5 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ origins:
- http://localhost:3000
- http://localhost:3001
- http://localhost:5000
validation:
enable: true
schemas:
- type: OpenApi
url: https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json
# ext_helpers: "./custom_handlebar.json"
# ext_data_source:
# pg:
Expand Down
Binary file added docs/MockValidation.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ Camouflage is a service virtualization tool inspired by [namshi/mockserver](http
🎊 Deployable on standalone VMs, Dockers and Kubernetes. 🎊

📁 Comes with a file explorer UI that allows modification of mock files hosted remotely. 📁

✅ Validation of requests and responses using your OpenApi schema's. ✅
181 changes: 181 additions & 0 deletions docs/validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
When testing software using a mock server it's important that your mocks are correct/valid to avoid false assumptions.

Contract testing is a grest methodology for ensuring that two separate systems are compatible and can communicate with one other.​

What sets this form of testing apart from other approaches that aim to achieve the same thing, is that each system can be tested independently from the other and that the contract is generated by the code itself, meaning the contract is always kept up to date with reality.​

![Mock validation using Contract Testing](MockValidation.png)

## OpenApi schema validation

Camouflage server support OpenApi schema's for request and response validation. When enabled the configured schema's are loaded in memory and each request and response simply need to adhere to the rules in schema.

### Configuration Options

By default, validation is disabled. To specify any of these optional configurations, modify config.yml in following way.

```yaml
validation:
enable: true
schemas:
- type: OpenApi
url: https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json
```

### Example

Now when you have a mock for the supported endpoint `/pets` requesting it would result in a proper response.

```
HTTP/1.1 200 OK
Content-Type: application/json
[
{ "id": 1, "name": "Rabbit" },
{ "id": 2, "name": "Dog" },
{ "id": 3, "name": "Cat" },
{ "id": 4, "name": "Bird" }
]
```

#### Request validation

Given this schema for `/pets` we see that the only support parameter is the integer `limit`

```json
{
"openapi": "3.0.0",
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
"parameters": [
{
"name": "limit",
"in": "query",
"description": "How many items to return at one time (max 100)",
"required": false,
"schema": {
"type": "integer",
"format": "int32"
}
}
]
...
}
}
}
```

Called with an unsupported paraemeter like `/pets?unsupported=1` will result in the following 400 error.

```json
[
{
"path": "page",
"errorCode": "type.openapi.requestValidation",
"message": "unknown query parameter 'unsupported'",
"location": "query"
}
]
```

Called with a wrong type like `/pets?limit=abc` will also result in the following 400 error.

```json
[
{
"path": "limit",
"errorCode": "type.openapi.requestValidation",
"message": "must be integer",
"location": "query"
}
]
```

#### Response validation

Given this schema for `/pets` we see that a pet has two required properties `id` and `name`.

```json
{
"openapi": "3.0.0",
"paths": {
"/pets": {
"get": {
"summary": "List all pets",
"operationId": "listPets",
...
"responses": {
"200": {
"description": "A paged array of pets",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
...
}
}
"components": {
"schemas": {
"Pet": {
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
},
...
}
}
}
```

In case previously your backend api did only had a required property `id` your assumptions in the tests are false.

```
HTTP/1.1 200 OK
Content-Type: application/json

[
{ "id": 1, "name": "Rabbit" },
{ "id": 2, "name": "Dog" },
{ "id": 3, "name": "Cat" },
{ "id": 4 }
]
```

Responses with the following mock will be blocked with a 409 response helping you to avoid mistakes.

```json
[
{
"path": "3",
"errorCode": "required.openapi.responseValidation",
"message": "must have required property 'name'"
}
]
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ nav:
- tests.md
- back-up-and-restore.md
- openAPI-conversion.md
- validation.md
- configuring-cache.md
- using-with-docker.md
- using-with-kubernetes.md
Expand Down
9 changes: 9 additions & 0 deletions mocks/pets/GET.mock
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
HTTP/1.1 200 OK
Content-Type: application/json

[
{ "id": 1, "name": "Rabbit" },
{ "id": 2, "name": "Dog" },
{ "id": 3, "name": "Cat" },
{ "id": 4, "name": "Bird" }
]

0 comments on commit f6f7601

Please sign in to comment.