adjective (of a product) made or used as a substitute, typically an INFERIOR one, for something else.
Creates a stub API server using a simple configuration file you provide.
go get github.com/peteclark-ft/ersatz
First create a ersatz-fixtures.yml
file (see full example file here), to stub specific API calls. By default, ersatz
expects your fixtures file to be in the _ft
folder at the root of your project.
For example, to stub an /__health
API call, you can use the following configuration:
version: 2.0.0 # the ersatz fixtures version. Releases will try to be backwards compatible
fixtures:
/__health: # the path of the stub
get: # the http method
status: 200 # the response status code to use
headers: # a map of http response headers to values
content-type: application/json
body: # the body of the response - this will be serialised to match the content-type (if provided, otherwise json is the default)
id: health-check
ok: false
Similarly, to stub a /__gtg
API call:
/__gtg:
get:
status: 200
headers:
content-type: plain/text; charset=US-ASCII
body: OK # supports plaintext responses
Once you have created your file, start ersatz
with:
ersatz
You can optionally specify a port and fixtures file to use:
ersatz -p 8080 -f ./_ft/ersatz-fixtures.yml
The recommended way to run ersatz
and dredd
via CircleCI is to use the ersatz
Docker container. This prevents ersatz
conflicting with your project's dependencies. First, add the following dredd
hook script to your project, and reference it in your dredd.yml
:
var hooks = require('hooks');
var http = require('http');
var fs = require('fs');
hooks.beforeAll(function(t, done) {
var contents = fs.readFileSync('./_ft/ersatz-fixtures.yml', 'utf8');
var options = {
host: 'localhost',
port: '9000',
path: '/__configure',
method: 'POST',
headers: {
'Content-Type': 'application/x-yaml'
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
});
req.write(contents);
req.end();
done();
});
Then configure your dredd build to run ersatz in a secondary container (make sure you change the following config to use appropriate docker container versions for your app):
dredd:
working_directory: /go/src/github.com/Financial-Times/draft-content-api
docker:
- image: bankrs/golang-dredd:gox.x.x-dreddx.x.x
environment:
GOPATH: /go
...
- image: peteclark-ft/ersatz:stable
steps:
- checkout
- run:
name: External Dependencies
command: |
go get -u github.com/kardianos/govendor
- run:
name: Govendor Sync
command: govendor sync -v
- run:
name: Go Build
command: go build -v
- run:
name: Dredd API Testing
command: dredd
The following ersatz docker versions are supported:
latest
- is the latest commit to masterstable
- is the latest full release tag in Githubx.x.x
- specific tag versions (see Releases for more information)
Here is an example REST configuration for a /{uuid}
, supporting GET
, PUT
and DELETE
:
/85be197c-4fda-407b-8ae3-28bd81978616: # IMPORTANT: Paths must match exactly, as ersatz doesn't do anything clever with them. In this case, all other uuids will 404.
get:
status: 200
body:
content:
title: Example Title
put:
status: 201
body:
message: Created ok
delete:
status: 204
Example redirect configuration to google.com:
/redirect-me:
get:
status: 301
headers:
Location: http://www.google.com
Example endpoint with a request discriminator. In some cases, the same endpoint path will respond differently to different input queryParams
or headers
, and so you need to discriminate between them. Ersatz will respond with a 501 Unimplemented
to requests that do no match any of the configured requests, which should cause your sandbox tests to fail.
/id:
get:
- when: # When the request has the following headers and queryParams
headers:
x-user: the-first-user
queryParams:
id: the-first-id
response: # Respond with the following
status: 200
headers:
x-returned-header: returned
- when: # Otherwise, when the request has the following headers and queryParams
headers:
x-user: the-second-user
queryParams:
id: the-second-id
response: # Respond slightly differently
status: 200
headers:
x-returned-header: a-different-header
Ersatz also supports a basic syntax for specifying discriminators for when headers are any value, or are missing.
/search:
get:
- when:
queryParams:
q: ${exists} # if a query param "q" exists
response: # Respond with the following
status: 200
body:
search_results:
- id: 1
- when: # Otherwise, if the request has no query param "q"
queryParams:
q: ${missing}
response:
status: 400
body:
msg: Please supply a "q" query param
- It's useful for local developer testing - you'd no longer need to point your local machine to real services in a test cluster.
ersatz-fixtures.yml
files can be committed along with the codebase, so new developers can re-use your stubs to get up and running quickly.- We can use it to simulate complex dependencies in CircleCI, allowing us to more easily test our OpenAPI files using DreddJS
- Support OpenAPI for more accurate stubs
- Comparisons between fixtures and the real API it is mocking
- Regex Discriminators