A MockPool is a Pool that intercepts requests matching registered routes
and replies with mocked responses instead of contacting the network. It is
created by a MockAgent and exposes the same interception API as
MockClient.
A MockPool is not constructed directly in most cases; instead it is obtained
through [mockAgent.get(origin)][]. Once registered as the global dispatcher,
any request whose origin matches the pool is matched against the mocks it holds.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')class MockPool extends PoolExtends Pool and implements the Interceptable interface, allowing
requests made through it to be matched against registered mocks.
new MockPool(origin, options?): MockPool<string><MockPoolOptions>Pool
options.<MockPool>The agent option is required and must implement the Agent interface;
otherwise an InvalidArgumentError is thrown.
Extends: PoolOptions
<MockAgent><boolean>false
.mockPool.intercept(options): MockInterceptor<MockPoolInterceptOptions><MockInterceptor>Registers a route on the mock pool and returns a MockInterceptor for any
matching request that uses the same origin as this mock pool. The interceptor is
then used to define the reply, for example with reply() or replyWithError().
Each intercept() call is consumed by a single matching request. To match more
than one request, call intercept() once per expected request, or use
persist() or times() on the returned MockScope. When no registered
mock matches a request, a real request is attempted unless network connections
have been disabled on the MockAgent, in which case a MockNotMatchedError
is thrown.
A request is intercepted only when every defined matcher passes. The accepted matcher forms behave as follows:
| Matcher type | Condition to pass |
|---|---|
string | Exact match against the value |
RegExp | The expression must match |
Function | The function must return true |
<string>
|
<RegExp>
|
<Function>(path: string) => boolean
. When a
RegExp
or function is used, it matches against the request path including all query
parameters in alphabetical order. When a
string
is used, query parameters
can instead be supplied through
query
.<string>
|
<RegExp>
|
<Function>(method: string) => boolean
.
Default:
'GET'
.<string>
|
<RegExp>
|
<Function>(body: string) => boolean
.<Object>
|
<Function>string
,
RegExp
, or
(value: string) => boolean
matcher, or as a single function that receives
all headers and returns a
boolean
. When a map is used, the request must
match every defined header; extra headers not listed here do not affect
matching.<Object>string
was provided for
path
.<boolean>path
is ignored
when matching. Inherited from the mock pool's
ignoreTrailingSlash
option
when not set.The reply behaviour of a matching request is defined through the returned
MockInterceptor.
reply(statusCode[, data[, responseOptions]])<Function>Defines the reply for a matching request.AttributesstatusCode:<number>The status code of the mocked reply.data:<string>|<Buffer>|<Object>|<Function>The body of the mocked reply. Objects are serialized to JSON; strings andBuffers are sent as-is. The function form has the signature(opts: MockResponseCallbackOptions) => string | Buffer | Objectand is invoked with the incoming request to compute the reply body.responseOptions?:<MockResponseOptions>Additional reply options. Default:{}.Returns:<MockScope>reply(callback)<Function>Defines the reply for a matching request, computing all reply options dynamically rather than just the body.Attributescallback:<Function>A(opts: MockResponseCallbackOptions) => { statusCode, data, responseOptions }function invoked with the incoming request.Returns:<MockScope>replyWithError(error)<Function>Defines an error for a matching request to throw.Attributeserror:<Error>The error thrown when a request matches.Returns:<MockScope>defaultReplyHeaders(headers)<Function>Sets default headers included on every subsequent reply defined on this interceptor, in addition to any headers set on a specific reply.Attributesheaders:<Object>A map of header name to value.Returns:<MockInterceptor>defaultReplyTrailers(trailers)<Function>Sets default trailers included on every subsequent reply defined on this interceptor, in addition to any trailers set on a specific reply.Attributestrailers:<Object>A map of trailer name to value.Returns:<MockInterceptor>replyContentLength()<Function>Sets an automatically calculatedcontent-lengthheader on every subsequent reply defined on this interceptor.Returns:<MockInterceptor>
By default, reply() and replyWithError() define the behaviour for the first
matching request only; subsequent requests are not affected unless persist()
or times() is used on the returned MockScope.
The argument passed to the reply() data and options callbacks.
A MockScope is associated with a single MockInterceptor and configures
how many times the defined reply is used.
delay(waitInMs)<Function>Delays the associated reply by a set amount of time.AttributeswaitInMs:<number>The delay in milliseconds.Returns:<MockScope>persist()<Function>Makes the associated reply match indefinitely, so every matching request receives the defined response.Returns:<MockScope>times(repeatTimes)<Function>Makes the associated reply match a fixed number of times. This is overridden bypersist().AttributesrepeatTimes:<number>The number of matching requests the reply applies to.Returns:<MockScope>
The following examples show common interception patterns.
import { MockAgent, setGlobalDispatcher, request } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({ path: '/foo' }).reply(200, 'foo')
const { statusCode, body } = await request('http://localhost:3000/foo')
console.log('response received', statusCode) // response received 200
for await (const data of body) {
console.log('data', data.toString('utf8')) // data foo
}mockPool.close(): Promise<Promise>undefined
once the mock pool is closed.Closes the mock pool, gracefully waiting for any enqueued requests to complete,
and removes it from the associated MockAgent.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')
await mockPool.close()mockPool.dispatch(options, handlers): boolean<DispatchOptions><DispatchHandler><boolean>false
if the dispatcher is busy and the caller should
wait before dispatching further requests, otherwise
true
.Dispatches a request, matching it against the registered mocks. This override of
dispatcher.dispatch(options, handlers) is what drives the mocking
behaviour for every higher-level method such as request.
mockPool.request(options, callback?): Promise<DispatchOptions><Function>Promise
is requested.<Promise>callback
is
provided.Performs a request and resolves it against the registered mocks. Inherited from
Pool; see [dispatcher.request(options[, callback])][] for the full
parameter and return value documentation.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo')
const { statusCode, body } = await mockPool.request({
origin: 'http://localhost:3000',
path: '/foo',
method: 'GET'
})
console.log('response received', statusCode) // response received 200
for await (const data of body) {
console.log('data', data.toString('utf8')) // data foo
}mockPool.cleanMocks(): undefined<undefined>Removes all registered interceptors from the mock pool. Pending mocks defined before this call no longer match incoming requests.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({ path: '/foo' }).reply(200, 'foo')
mockPool.cleanMocks()[dispatcher.request(options[, callback])]: Dispatcher.md#dispatcherrequestoptions-callback
[mockAgent.get(origin)]: MockAgent.md#mockagentgetorigin