A MockAgent is a <Dispatcher> that intercepts HTTP requests made through
undici and replies with programmed mock responses instead of contacting the
network. It is useful for testing code that performs HTTP requests without
relying on a live server.
A MockAgent does not intercept requests on its own. Mock responses are
registered on the <MockClient> or <MockPool> instances returned by mockAgent.get(origin), and requests are routed through them once the
MockAgent is set as the dispatcher (for example through
setGlobalDispatcher() or a per-request dispatcher option).
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()class MockAgent extends DispatcherIntercepts HTTP requests made through undici and returns mocked responses.
MockAgent Constructor
History
Mock options are always normalized to an object internally.
new MockAgent(options?): MockAgent<MockAgentOptions><MockAgent>When instantiated, a MockAgent is automatically activated. It does not
intercept any request until mock interceptors are registered on the dispatchers
returned by mockAgent.get(origin).
<AgentOptions><Dispatcher>MockAgent
. It must implement the
Agent
API (that is, expose a
dispatch
function).
Default:
a new
<Agent>
constructed from
options
.<boolean>false
.<boolean>[]
(for example
param[]=1¶m[]=2
) or
comma-separated values (for example
param=1,2,3
).
Default:
false
.<boolean>mockAgent.getCallHistory()
.
Default:
false
.import { MockAgent } from 'undici'
const mockAgent = new MockAgent()mockAgent.get(origin): MockClient | MockPool<string>
|
<RegExp>
|
<Function>(origin) => boolean
.<MockClient>
|
<MockPool>Creates and retrieves the mock dispatcher used to intercept requests for the
given origin. When the connections option of the MockAgent is 1, a
<MockClient> is returned; otherwise a <MockPool> is returned. Subsequent calls
with the same origin return the same instance.
The way origin is matched against incoming requests depends on its type:
| Matcher type | Condition to pass |
|---|---|
string | Exact match against the value |
RegExp | The regular expression matches |
Function | The function returns true |
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
}mockAgent.dispatch(options, handler): boolean<AgentDispatchOptions><DispatchHandler><boolean>Dispatches a mocked request. This implements
Dispatcher.dispatch() for the encapsulated agent: it ensures the mock
dispatcher for options.origin exists, records the call in the call history
when enabled, and forwards the request to the underlying agent. It is normally
invoked indirectly through higher-level methods such as
mockAgent.request().
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({ path: '/foo' }).reply(200, 'foo')
const { statusCode, body } = await mockAgent.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
}mockAgent.close(): Promise<void>Clears the call history, closes the encapsulated agent, and waits for all registered mock pools and clients to close.
import { MockAgent, setGlobalDispatcher } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
await mockAgent.close()mockAgent.deactivate(): undefined<undefined>Disables mocking on the MockAgent. While deactivated, requests are no longer
intercepted.
import { MockAgent, setGlobalDispatcher } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
mockAgent.deactivate()mockAgent.activate(): undefined<undefined>Enables mocking on the MockAgent. A MockAgent is activated automatically
when instantiated, so this method is only required after
mockAgent.deactivate() has been called.
import { MockAgent, setGlobalDispatcher } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
mockAgent.deactivate()
// No mocking will occur
// Later
mockAgent.activate()mockAgent.enableNetConnect(matcher?): undefined<string>
|
<RegExp>
|
<Function>(host) => boolean
. When omitted, all
non-matching requests are allowed to perform a real request.<undefined>Defines host matchers so that requests that are not intercepted by a mock dispatcher are allowed to perform a real HTTP request. Calling this method multiple times with a string appends each value to the list of allowed hosts.
import { MockAgent, setGlobalDispatcher, request } from 'undici'
const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)
mockAgent.enableNetConnect()
await request('http://example.com')
// A real request is mademockAgent.disableNetConnect(): undefined<undefined>Causes every request that is not matched by a mock interceptor to throw, disallowing real HTTP requests.
import { MockAgent, request } from 'undici'
const mockAgent = new MockAgent()
mockAgent.disableNetConnect()
await request('http://example.com')
// Will throwmockAgent.enableCallHistory(): MockAgent<MockAgent>MockAgent
instance, for chaining.Enables call history recording. Once enabled, subsequent calls are registered
and can be retrieved through mockAgent.getCallHistory(). Call history can
also be enabled at construction time with the enableCallHistory option.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
mockAgent.enableCallHistory()mockAgent.disableCallHistory(): MockAgent<MockAgent>MockAgent
instance, for chaining.Disables call history recording. Subsequent calls are no longer registered.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent({ enableCallHistory: true })
mockAgent.disableCallHistory()mockAgent.getCallHistory(): MockCallHistory | undefined<MockCallHistory>
|
<undefined><MockCallHistory>
instance, or
undefined
when call history is not enabled.Returns the call history instance, which records every request made through the
MockAgent (whether intercepted or not). Call history is not enabled by
default; enable it with the enableCallHistory option or
mockAgent.enableCallHistory().
import { MockAgent, setGlobalDispatcher, request } from 'undici'
const mockAgent = new MockAgent({ enableCallHistory: true })
setGlobalDispatcher(mockAgent)
await request('http://example.com', { query: { item: 1 } })
mockAgent.getCallHistory()?.firstCall()
// Returns
// MockCallHistoryLog {
// body: undefined,
// headers: undefined,
// method: 'GET',
// origin: 'http://example.com',
// fullUrl: 'http://example.com/?item=1',
// path: '/',
// searchParams: { item: '1' },
// protocol: 'http:',
// host: 'example.com',
// port: ''
// }mockAgent.clearCallHistory(): undefined<undefined>Clears the call history, deleting every recorded <MockCallHistoryLog> on the
<MockCallHistory> instance. It is a no-op when call history has never been
enabled.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent({ enableCallHistory: true })
mockAgent.clearCallHistory()mockAgent.pendingInterceptors(): PendingInterceptor<PendingInterceptor>Returns the interceptors registered on the MockAgent that are still pending.
An interceptor is pending when it meets one of the following criteria:
- It is registered with neither
.times(<number>)nor.persist()and has not been invoked. - It is persistent (registered with
.persist()) and has not been invoked. - It is registered with
.times(<number>)and has not been invoked<number>times.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
mockAgent.disableNetConnect()
mockAgent
.get('https://example.com')
.intercept({ method: 'GET', path: '/' })
.reply(200)
const pendingInterceptors = mockAgent.pendingInterceptors()
// Returns [
// {
// timesInvoked: 0,
// times: 1,
// persist: false,
// consumed: false,
// pending: true,
// path: '/',
// method: 'GET',
// body: undefined,
// headers: undefined,
// data: {
// error: null,
// statusCode: 200,
// data: '',
// headers: {},
// trailers: {}
// },
// origin: 'https://example.com'
// }
// ]mockAgent.assertNoPendingInterceptors(options?): undefined<undefined>Throws an <UndiciError> when the MockAgent has any pending interceptors. The
criteria for an interceptor being pending are the same as for
mockAgent.pendingInterceptors().
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
mockAgent.disableNetConnect()
mockAgent
.get('https://example.com')
.intercept({ method: 'GET', path: '/' })
.reply(200)
mockAgent.assertNoPendingInterceptors()
// Throws an UndiciError with the following message:
//
// 1 interceptor is pending:
//
// ┌─────────┬────────┬───────────────────────┬──────┬─────────────┬────────────┬─────────────┬───────────┐
// │ (index) │ Method │ Origin │ Path │ Status code │ Persistent │ Invocations │ Remaining │
// ├─────────┼────────┼───────────────────────┼──────┼─────────────┼────────────┼─────────────┼───────────┤
// │ 0 │ 'GET' │ 'https://example.com' │ '/' │ 200 │ '❌' │ 0 │ 1 │
// └─────────┴────────┴───────────────────────┴──────┴─────────────┴────────────┴─────────────┴───────────┘<boolean>A read-only property indicating whether mocking is currently active on the
MockAgent.
import { MockAgent } from 'undici'
const mockAgent = new MockAgent()
console.log(mockAgent.isMockActive) // true
mockAgent.deactivate()
console.log(mockAgent.isMockActive) // false