Skip to main content

Testing Reference

Everything on this page is exported from openapi-backend/testing:

import { createTestClient, lambda, RoutingError, ResponseValidationError } from 'openapi-backend/testing';
import type { TestClient, TestRequest, TestResponse, SentRequest, TestAdapter } from 'openapi-backend/testing';

createTestClient(api, options?)​

Creates a test client for an OpenAPIBackend instance.

import { createTestClient } from 'openapi-backend/testing';
import type { Operations } from './types/openapi';

const client = createTestClient<Operations>(api, { app });

The type parameter is optional. Pass the Operations type generated by openapi typegen --backend to type operation methods.

The client initializes api on its first request, if it isn't initialized yet.

Options​

OptionTypeDescription
appTestAppWhere to send requests. See Frameworks.
transformResponsefunctionWithout app: turns the value api.handleRequest() returns into a response. See No framework.
basePathstringPath prepended to the paths of operations. Default: api.apiRoot
headersobjectHeaders for every request
queryobjectQuery parameters for every request
cookiesobjectCookies for every request
securityobjectSecurity handler stubs for every request
exampleboolean or stringBuild every request from examples
validateResponsebooleanCheck responses against the spec. Default: true

Either app or transformResponse is required.

TestClient​

client.operationId(request?)​

Every operation in your API definition has a method named after its operationId.

Builds a request for the operation, sends it, and resolves to a TestResponse for any status code. Throws:

  • an Error if the operation doesn't exist, or a path parameter is missing
  • a RoutingError if the request is routed to another operation, or to none
  • a ResponseValidationError if the response doesn't match the spec, unless validateResponse is false
const res = await client.getPetById({ params: { id: 1 } });

Parameters:

Returns: Promise<TestResponse>

client.call(operationId, request?)​

The same as calling the operation method. For table-driven tests, and operations whose operationId clashes with a client method.

const res = await client.call('getPetById', { params: { id: 1 } });

client.request(request, options?)​

Sends a raw request, without building it from an operation. If the router matches an operation, the response is still checked against the spec.

await client.request('GET /pets?limit=10');
await client.request('POST /pets', { body: { name: 'Garfield' } });
await client.request({ method: 'GET', path: '/pets', query: { limit: 10 } });

Parameters:

  • request: a string with the method, path and an optional query string, or an object with method and path
  • options: TestRequest, without params and example

Returns: Promise<TestResponse>

client.with(defaults)​

Returns a new client that adds defaults to every request. defaults takes the same options as TestRequest, except params and body. The original client doesn't change.

const alice = client.with({ headers: { authorization: `Bearer ${token}` } });

client.api​

The OpenAPIBackend instance the client was created for.

TestRequest​

Options for a request. All are optional.

OptionTypeDescription
paramsobjectPath parameters. Filled into the path template and URL-encoded.
queryobjectQuery parameters. Serialized with the style and explode of each parameter in the spec.
headersobjectRequest headers. Arrays are sent as comma separated values.
cookiesobjectCookies, sent in the Cookie header
bodyunknownThe request body. Objects are encoded as the operation's media type. Strings, Buffers, URLSearchParams and FormData are sent as they are.
contentTypestringThe media type to send the body as. Default: the operation's media type, preferring application/json
exampleboolean or stringtrue builds the request from the spec's examples, a string picks a named example. Other options are deep merged into it.
securityobjectResults to use instead of calling the security handlers, by security scheme name
validateResponsebooleanfalse skips checking the response against the spec

Options passed to a request override defaults from createTestClient() and client.with(). headers, query, cookies and security are merged key by key. Setting a key to undefined removes it.

TestResponse​

PropertyTypeDescription
statusnumberThe HTTP status code
headersobjectResponse headers, with lowercase names. Several values for one header are joined with , .
bodyanyThe body. JSON is parsed. Other text is a string, binary content is a Buffer, and an empty body is undefined. Typed from your spec with a typed client.
operationIdstring or undefinedThe operation the request was routed to
operationOperation or undefinedThe matched Operation object
contextContextThe Context object openapi-backend built for the request. undefined if the request never reached api.handleRequest() in the same process.
requestSentRequestThe request that was sent

operation, context and request aren't enumerable.

SentRequest​

The request the client sent. It's also a valid openapi-backend Request object.

PropertyTypeDescription
methodstringThe HTTP method, in uppercase
pathstringThe path, without the query string
urlstringThe path, with the query string
querystringThe query string, without the ?
headersobjectThe request headers, with lowercase names
bodystring, Buffer or undefinedThe encoded body

lambda(handler, options?)​

Creates an adapter that sends requests to an AWS Lambda handler as API Gateway events. See Frameworks.

import { createTestClient, lambda } from 'openapi-backend/testing';

const app = lambda(handler, { event: 'v2' });
const client = createTestClient(api, { app });
OptionTypeDescription
event'v1' or 'v2''v1' for API Gateway REST API events, 'v2' for HTTP API and function URL events (payload format 2.0). Default: 'v1'
contextobjectProperties of the Lambda context object passed to the handler

Handlers can return a promise or call the callback. The response is read from the statusCode, headers, multiValueHeaders, cookies and body of the result, and base64 encoded bodies are decoded. Like API Gateway, a result without a content-type header is sent as application/json, and with 'v2', a result without a statusCode is sent as a 200 JSON response.

TestApp​

What you can pass as the app option:

  • an Express, Koa or Fastify app, or a Hapi server
  • an http.Server, or a Node.js (req, res) request listener
  • an object with a fetch(request) method that returns a Response
  • a URL string, to send requests to a running server
  • a TestAdapter: an adapter created with lambda(), or your own object with a send() method
interface TestAdapter {
send(request: SentRequest): TestAdapterResponse | Response | Promise<TestAdapterResponse | Response>;
}

interface TestAdapterResponse {
status: number;
headers?: { [name: string]: string | string[] | number | undefined };
body?: unknown;
}

String and Buffer bodies are parsed according to the content-type header. Other values are used as the body as they are. transformResponse returns the same.

Errors​

RoutingError​

Thrown by operation methods when the request built for an operation is routed to another operation, or to none. See Operation methods check routing too.

PropertyDescription
operationIdThe operation the request was built for
matchedOperationIdThe operation the router matched, or undefined
requestThe SentRequest

ResponseValidationError​

Thrown when a response doesn't match the spec. See Contract testing.

PropertyDescription
responseThe TestResponse
errorsWhat didn't match, each with a location, like status, headers.content-type or body.name, and a message