OpenAPI Conventions
🗓️ Last updated on May 27, 2024 | 5 | Improve this pageConventions
In addition of schema information, Microcks uses OpenAPI Example Objects to produce working mocks and build test suite for validating your implementation.
As example fragments are actually distributed along the OpenAPI specification, Microcks collects fragments and try to associate them by name. Microcks only takes care of comprehensive request/response examples - which means that if you provide examples for input elements (parameter
, requestBody
) but not for output (response
), incomplete examples will be discarded.
Illustration
The Cars sample . It is a simple API that allows registering cars to an owner, listing cars for this owner and adding passenger to a car. Within this sample specification, we have defined 2 mocks - one for the registering operation and another for the listing cars operation:
- The
POST /owner/{owner}/car
operation defines a sample calledlaurent_307
where we’ll register a Peugeot 307 for Laurent, - The
GET /owner/{owner}/car
operation defines a sample calledlaurent_cars
where we’ll list the cars owned by Laurent.
Specifying request params
Specifying request params encompasses path params, query params and header params. Within our two examples, we have to define the owner
path param value - one for laurent_307
mock and another for laurent_cars
mock.
Path parameters
This is done within the parameters
part of corresponding API path
, on line 83
of our file:
parameters:
- name: owner
in: path
description: Owner of the cars
required: true
schema:
format: string
type: string
examples:
laurent_cars:
summary: Value for laurent related examples
value: laurent
laurent_307:
$ref: '#/components/examples/param_laurent'
One thing to notice here is that Microcks importer supports the use of references like '#/components/examples/param_laurent'
to avoid duplication of complex values.
Query parameters
Query parameters are specified using parameters defined under the verb
of the specification as you may find on line 20
. Snippet is represented below for the laurent_cars
mock:
- name: limit
in: query
description: Number of result in page
required: false
schema:
type: integer
examples:
laurent_cars:
value: 20
Specifying request payload
Request payload is used within our laurent_307
sample. It is specified under the requestBody
of the specification as you may find starting on line 55
. Request payload may refer to OpenAPI schema definitions like in the snippet below:
requestBody:
description: Car body
content:
application/json:
schema:
$ref: '#/components/schemas/Car'
examples:
laurent_307:
summary: Creation of a valid car
description: Should return 201
value: '{"name": "307", "model": "Peugeot 307", "year": 2003}'
required: true
Specifying response payload
Response payload is used within our laurent_cars
sample. It is defined under the Http status
of the specification as you may find starting on line 40
. Response payload may refer to OpenAPI schema definitions like in the snippet below:
responses:
200:
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Car'
examples:
laurent_cars:
value: |-
[
{"name": "307", "model": "Peugeot 307", "year": 2003},
{"name": "jean-pierre", "model": "Peugeot Traveller", "year": 2017}
]
No content response payload
Now let’s imagine the case where you’re dealing with an API operation that returns “No Content”. This could by - for example - an operation that takes care of deleting a car from the database and return a simple 204
HTTP response code once done.
In that case, we cannot rely on Example Objects
because the response has typically no content we can attach an example
to. We need another way to specify the matching of this response with an incoming request. For this, we introduced a specific x-microcks-refs
extension that allows to tell Microcks on which requests it should match this response.
Let’s illustrate the above-mentioned case with this snippet below:
/owner/{owner}/car/{car}:
delete:
parameters:
- name: owner
in: path
description: Owner of the cars
required: true
schema:
format: string
type: string
examples:
laurent_307:
value: laurent
laurent_jp:
value: laurent
- name: car
in: path
description: Owner of the cars
required: true
schema:
format: string
type: string
examples:
laurent_307:
value: '307'
laurent_jp:
value: 'jean-pierre'
responses:
204:
description: No Content
x-microcks-refs:
- laurent_307
- laurent_jp
When Microcks will receive DELETE /owner/laurent/car/307
or DELETE /owner/laurent/car/jean-pierre
call, it will just reply using a 204
HTTP response code.
💡 Note that this association also works if you defined some
requestBody
examples for the operation.
OpenAPI extensions
Microcks proposes custom OpenAPI extensions to specify mocks organizational or behavioral elements that cannot be deduced directly from OpenAPI document.
At the info
level of your OpenAPI document, you can add labels specifications that will be used in organizing the Microcks repository
. See below illustration and the use of x-microcks
extension:
openapi: 3.1.0
info:
title: OpenAPI Car API
description: Sample OpenAPI API using cars
contact:
name: Laurent Broudoux
url: https://github.com/lbroudoux
license:
name: MIT License
url: https://opensource.org/licenses/MIT
version: 1.1.0
x-microcks:
labels:
domain: car
status: beta
team: Team A
[...]
At the operation
level of your OpenAPI document, we could add delay/frequency and dispatcher specifications. These one will be used to customize the dispatching rules
to your API mocks. Let’s give an example for OpenAPI using the x-microcks-operation
extension:
[...]
post:
summary: Add a car to current owner
description: Add a car to current owner description
operationId: addCarOp
x-microcks-operation:
delay: 100
dispatcher: SCRIPT
dispatcherRules: |
def path = mockRequest.getRequest().getRequestURI();
if (!path.contains("/laurent/car")) {
return "Not Accepted"
}
def jsonSlurper = new groovy.json.JsonSlurper();
def car = jsonSlurper.parseText(mockRequest.getRequestContent());
if (car.name == null) {
return "Not Accepted"
}
return "Accepted"
[...]
💡 Note that we can use multi-line notation in YAML but we will have to escape everything and put
\
before double-quotes and\n
characters if specified using JSON.
Once labels
and dispatching rules are defined that way, they will overwrite the different customizations you may have done through UI or API during the next import of the OpenAPI document.
Still Didn’t Find Your Answer?
Join our community and get the help you need. Engage with other members, ask questions, and share knowledge to resolve your queries and expand your understanding.
Join the community