YAML config file
Notation: The following conventions are used in the syntax description: Brackets "[" and "]" indicate optional parts. Brackets "<" and ">" indicate mandatory parts. Vertical lines "|" indicate that you must choose one alternative. All other symbols, including parentheses, should be taken literally.File name and location
The gRPC service mock configuration file should be named ".grpc.mock.qa.yaml" and placed in the root of the repository. The endpoint for this mock service will be https://[[instanceName→]repo→]<owner>.grpc.qa
. The HTTP service mock configuration file should be named ".http.mock.qa.yaml" and also placed in the root of the repository. The endpoint for this mock service will be https://[[instanceName→]repo→]<owner>.rest.qa
. You can have both files at the same time in the same repository, both the gRPC and HTTP mock service will work as expected.
gRPC service mock
Configuration file: | /.grpc.mock.qa.yaml |
Endpoint: | https://[[instanceName→]repo→]<owner>.grpc.qa |
HTTP service mock
Configuration file: | /.http.mock.qa.yaml |
Endpoint: | https://[[instanceName→]repo→]<owner>.rest.qa |
File layout
Below are depicted names of all main sections of yaml file but without their content:
### Header section
fileVersion: v1
instanceName: <string>
protoFile: <string>
### Channel credentials section
channel: # optional
credentials: <mapping> # optional
### Calls section
calls:
- method: <string> # gRPC method in the format <package>.<Service>/<Method>,
# for example greet.Greeter/SayHello
debugName: <string> # optional, default "GRPC <method> #N",
# in use for trace logging only
credentials: <sequence> # optional, same as channel.credentials
scenario: <mapping> # optional, stateful testing
request: # optional
header: # optional
body|stream: # optional
response: # optional
header: # optional
body|stream: # optional
trailer: # optional
status: # optional
statusDetails: # optional
Header section
A YAML file defines the version of the file, the instance name of the service, and the location of the gRPC protobuf .proto file that defines the service interfaces.
---
# constant version number
fileVersion: v1
# a unique name of a mock service instance.
# Part of the endpoint URL https://[[instanceName→]repo→]<owner>.grpc.qa
instanceName: <string>
# an absolute path to the .proto file in your github repository (for gRPC mocks only)
protoFile: <string>
Channel credentials section
You can define your authentication and authorization settings for a gRPC service. A channel section defines the credentials that are applied for the whole service.
encrypted-string is a secured string that has been encrypted using asymmetric RSA algorithm. Please find Encrypt a string
dialog in the mock.qa dashboard Tools
menu.
channel:
credentials:
- type: basic-auth
user: <string>
password: <string>
- type: jwt-bearer
authority: <string>
audience: <string> # optional
claims: <string> # optional
- type: ip-white-list
allowedIps: <sequence>
- type: client-certificate
clientCertificateThumbprints: <sequence> # optional
trustedRootCertificateFiles: <sequence> # optional
Calls section
A list of calls, each of which defines a specific gRPC or HTTP method that the mock service can handle.
# .grpc.mock.qa.yaml:
calls:
- method: <string> # gRPC method in the format <package>.<Service>/<Method>,
# for example greet.Greeter/SayHello
debugName: <string> # optional, default "GRPC <method> #N",
# in use for trace logging only
credentials: <sequence> # optional, same as channel.credentials
scenario: # optional, stateful testing
request: # optional
response: # optional
# .http.mock.qa.yaml:
calls:
- url: <string> # http url, should start with "/", supports templates,
# for example /post/{id}
method: <GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH>
debugName: <string> # optional, default "HTTP <method> <url> #N",
# in use for trace logging only
credentials: <sequence> # optional, same as channel.credentials
scenario: # optional, stateful testing
request: # optional
response: # optional
Call credentials section
Calls may include a credentials section that specifies the type of authentication that should be used for a particular call. This section is separate from the channel credentials, and its structure is similar to that of channel credentials. The credentials section does not overwrite the channel credentials but rather supplements them if any channel credentials have already been specified.
credentials:
- type: basic-auth
user: user
password: "$RSA2048:rldEHit9cK7kvhAMPBJBU+YloFipXa8Hnr30S0b8Lgbsdd54NWzyo4k0nCLeSWqsW4U7LJXSTrVjGs0VmmA1l7QFadOIHsqYU8mUToIREq9y8xfSo8M7dzSsbYuqTKUiz5oDWEufzzvy0fNGsUHgdw+pQyaePPMPkYHJE8y31JR61atLM8LorEGmKCAuy/YUEF2UHfNXIQjebncZbbSpe1P1KZ5z5l7UwJhgFVEhMO7WpWTqpHoL8kWYT0FotYtQQXAGLzTys1XEcxlrI4rWtnEZwKSx9ifC1PpIVXp7hgVpZ8BjffVyLtc6V1bkoBfaSEWUFPLX/GWhBWXLFL5zwQ=="
Call scenario section
Calls may include a scenario section for stateful scenarios in order to implement state machine behavior.
A call will be a match if the scenario.name
scenario has a state scenario.requiredState
(in addition to request payload matching rules specified in the call
section). Once a call is matched, the scenario.name
scenario state will be set to scenario.newState
.
All scenarios' initial state is started
.
scenario:
name: <string> # case-insensitive
requiredState: <string> # a state to match.
# Initial state is "started"
newState: <string> # a new state to set if a call is matched,
# optional
Call request section
The request section contains matching rules for a call. It consists of a header, body, and stream sections. It can include various conditions and values that the mock service should use when matching the gRPC to HTTP method calls.
in the example below request definition will match an incoming gRPC request SayHelloRequest { Name = "Joe" }
calls:
- method: greet.Greeter/SayHello
request:
body:
Name: "Joe"
- method: <string> # gRPC method in the format <package>.<Service>/<Method>,
# for example greet.Greeter/SayHello
request: # optional
header: <mapping> # optional
body|stream: <mapping|sequence> # optional
Call response section
The response section contains a response template if a call is matched. It may contain a body, stream (for gRPC only), header, trailer, and status sections for response templating.
# .grpc.mock.qa.yaml:
response: # optional
randomize: <bool> # optional, response.body will be randomized
header: # optional
trailer: # optional
body|stream: <mapping|sequence> # optional, for unary and streaming calls
status: <OK|CANCELLED|NOT_FOUND|...> # optional, default OK
statusDetails: <string> # optional, default empty
# .http.mock.qa.yaml:
response: # optional
header: # optional
body: <mapping|sequence> # optional
status: <int> # optional, default 200
Multiple mock instances in a single file
If you have multiple .proto services and want to create mocks for all of them, you can include multiple mock definitions in a single configuration file, as shown below:
---
fileVersion: v1 # constant
instanceName: instanceOne
protoFile: /one.proto
... the rest of the file ...
---
fileVersion: v1 # constant
instanceName: instanceTwo
protoFile: /two.proto
... the rest of the file ...
Alternatively, you can use our pre-processing feature to split the mock definitions into separate files for easier maintenance:
.grpc.mock.qa.yaml file content:
#include /one.yaml
#include /two.yaml
one.yaml file content:
---
fileVersion: v1 # constant
instanceName: instanceOne
protoFile: /one.proto
... the rest of the file ...
two.yaml file content:
---
fileVersion: v1 # constant
instanceName: instanceTwo
protoFile: /two.proto
... the rest of the file ...
Examples and demo repository
There is a dedicated repository that contains a collection of examples, please check it out:
File description: .grpc.mock.qa.yaml
Below is a formal description of a file structure:
# Please note:
# We use YAML terms for types definitions: scalar, sequence and mapping
# - scalar: matches a string, enum, bool, int, float, date, timestamp, duration.
# - sequence: matches an ordered list (protobuf: a repeated field).
# - mapping: matches a complex type (protobuf: a message type), or a dictionary (protobuf: a map).
---
fileVersion: v1 # constant
instanceName: <string> # a unique name of a mock service instance.
# Part of the endpoint URL https://[[instanceName→]repo→]<owner>.grpc.qa
protoFile: <string> # an absolute path to the .proto file in your github repository
channel: # optional
credentials: # sequence, one or many from the list below, optional
- type: basic-auth
user: <string>
password: <string>
- type: jwt-bearer
authority: <string>
audience: <string> # optional
claims: <string> # optional
- type: ip-white-list
allowedIps: <sequence>
- type: client-certificate
clientCertificateThumbprints: <sequence> # optional
trustedRootCertificateFiles: <sequence> # optional
calls:
- method: <string> # gRPC method in the format <Package>.<Service>/<Method>,
# for example greet.Greeter/SayHello
debugName: <string> # optional, default "GRPC <method> #N",
# in use for trace logging only
credentials: <sequence> # optional, same as channel.credentials
scenario: # optional, stateful testing
name: <string> # case-insensitive
requiredState: <string> # a state to match. Initial state is "started"
newState: <string> # optional, a new state to set if a call is matched
request: # optional
header: # optional
<arbitrary-key>: <scalar> # same as equalTo: <scalar>
<arbitrary-key>:
equalTo: <scalar>
lessThan: <scalar>
lessOrEqualTo: <scalar>
moreThan: <scalar>
moreOrEqualTo: <scalar>
contains: <scalar>
startsWith: <scalar>
endsWith: <scalar>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
body|stream: <mapping> # optional
equalTo: <scalar | mapping | sequence> # optional
contains: <scalar | mapping | sequence> # optional
startsWith: <scalar | mapping | sequence> # optional
endsWith: <scalar | mapping | sequence> # optional
matchesWildcard: <string> # optional
matchesRegEx: <string> # optional
matchesJPath: <string> # optional
matchesJsonFile: <string> # optional
matchesYamlFile: <string> # optional
...
<any-property>: <any-value> # shortcut to equalTo: <any-value>
...
<any-property>:
not:
<any-operator>
...
<scalar-property>:
equalTo: <scalar>
equivalentTo: <sequence> # like equalTo, but ignores casing
lessThan: <scalar>
lessOrEqualTo: <scalar>
moreThan: <scalar>
moreOrEqualTo: <scalar>
contains: <scalar>
startsWith: <scalar>
endsWith: <scalar>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
...
<mapping-property>:
equalTo: <scalar | mapping>
equivalentTo: <sequence> # like equalTo, but ignores an order
contains: <scalar | mapping>
startsWith: <scalar | mapping>
endsWith: <scalar | mapping>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
...
<sequence-property>:
count: <scalar | any-operator> # matches a count of elements
equalTo: <scalar | sequence>
equivalentTo: <sequence> # like equalTo, but ignores an order
contains: <scalar | sequence>
startsWith: <scalar | sequence>
endsWith: <scalar | sequence>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
...
response: # optional
randomize: <bool> # optional
header: # optional
<arbitrary-key>: <scalar>
...
trailer: # optional
<arbitrary-key>: <scalar>
...
body|stream: <mapping | sequence> # optional, for unary calls
fromJsonFile: <string> # optional
fromYamlFile: <string> # optional
...
<any-property>:
fromJsonFile: <string>
fromYamlFile: <string>
...
<scalar-property>: <scalar>
<mapping-property>: <mapping>
<sequence-property>: <sequence>
...
# https://grpc.github.io/grpc/core/md_doc_statuscodes.html
status: <OK|CANCELLED|UNKNOWN|...> # optional, default OK
statusDetails: <string> # optional, default empty
File description: .http.mock.qa.yaml
Below is a formal description of a file structure:
---
fileVersion: v1 # constant
instanceName: <string> # unique per repository
channel: # optional
credentials: # sequence, one or many from the list below, optional
- type: basic-auth
user: <string>
password: <string>
- type: jwt-bearer
authority: <string>
audience: <string> # optional
claims: <string> # optional
- type: ip-white-list
allowedIps: <sequence>
- type: client-certificate
clientCertificateThumbprints: <sequence> # optional
trustedRootCertificateFiles: <sequence> # optional
calls:
- url: <string> # http url, should start with "/", supports templates,
# for example /post/{id}
method: <GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH>
debugName: <string> # optional, default "HTTP <method> <url> #N",
# in use for trace logging only
credentials: <sequence> # optional, same as channel.credentials
scenario: # optional, stateful testing
name: <string> # case-insensitive
requiredState: <string> # a state to match. Initial state is "started"
newState: <string> # optional, a new state to set if a call is matched
request: # optional
header: # optional
<arbitrary-key>: <scalar> # same as equalTo: <scalar>
<arbitrary-key>:
equalTo: <scalar>
contains: <scalar>
startsWith: <scalar>
endsWith: <scalar>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
body: <mapping> # optional, for unary calls
equalTo: <scalar | mapping | sequence> # optional
contains: <scalar | mapping | sequence> # optional
startsWith: <scalar | mapping | sequence> # optional
endsWith: <scalar | mapping | sequence> # optional
matchesWildcard: <string> # optional
matchesRegEx: <string> # optional
matchesJPath: <string> # optional
matchesJsonFile: <string> # optional
matchesYamlFile: <string> # optional
...
<any-property>: <any-value> # shortcut to equalTo: <any-value>
...
<any-property>:
not:
<any-operator>
...
<scalar-property>:
equalTo: <scalar>
equivalentTo: <sequence> # like equalTo, but ignores casing
lessThan: <scalar>
lessOrEqualTo: <scalar>
moreThan: <scalar>
moreOrEqualTo: <scalar>
contains: <scalar>
startsWith: <scalar>
endsWith: <scalar>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
...
<mapping-property>:
equalTo: <scalar | mapping>
equivalentTo: <sequence> # like equalTo, but ignores an order
contains: <scalar | mapping>
startsWith: <scalar | mapping>
endsWith: <scalar | mapping>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
...
<sequence-property>:
count: <scalar | any-operator> # matches a count of elements
equalTo: <scalar | sequence>
equivalentTo: <sequence> # like equalTo, but ignores an order
contains: <scalar | sequence>
startsWith: <scalar | sequence>
endsWith: <scalar | sequence>
matchesWildcard: <string>
matchesRegEx: <string>
matchesJPath: <string>
matchesJsonFile: <string>
matchesYamlFile: <string>
response: # optional
header: # optional
<arbitrary-key>: <scalar>
...
body: <mapping> # optional, for unary calls
fromJsonFile: <string> # optional
fromYamlFile: <string> # optional
...
<any-property>:
fromJsonFile: <string>
fromYamlFile: <string>
...
<scalar-property>: <scalar>
<mapping-property>: <mapping>
<sequence-property>: <sequence>
...
status: <int> # optional, default 200