619 lines
19 KiB
Plaintext
619 lines
19 KiB
Plaintext
# MockPool
|
|
|
|
<!--introduced_in=v4.0.0-->
|
|
<!--type=module-->
|
|
<!-- source_link=lib/mock/mock-pool.js -->
|
|
|
|
> Stability: 2 - Stable
|
|
|
|
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.
|
|
|
|
```mjs
|
|
import { MockAgent } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
```
|
|
|
|
```cjs
|
|
const { MockAgent } = require('undici')
|
|
|
|
const mockAgent = new MockAgent()
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
```
|
|
|
|
## Class: `MockPool`
|
|
|
|
<!-- YAML
|
|
added: v4.0.0
|
|
-->
|
|
|
|
* Extends: {Pool}
|
|
|
|
Extends [`Pool`][] and implements the `Interceptable` interface, allowing
|
|
requests made through it to be matched against registered mocks.
|
|
|
|
### `new MockPool(origin[, options])`
|
|
|
|
<!-- YAML
|
|
added: v4.0.0
|
|
-->
|
|
|
|
* `origin` {string} The origin to associate this mock pool with. It should only
|
|
include the protocol, hostname, and port.
|
|
* `options` {MockPoolOptions} Extends the [`Pool`][] options.
|
|
* Returns: {MockPool}
|
|
|
|
The `agent` option is required and must implement the `Agent` interface;
|
|
otherwise an `InvalidArgumentError` is thrown.
|
|
|
|
#### Parameter: `MockPoolOptions`
|
|
|
|
Extends: `PoolOptions`
|
|
|
|
* `agent` {MockAgent} The agent to associate this mock pool with.
|
|
* `ignoreTrailingSlash` {boolean} Whether trailing slashes should be ignored
|
|
when matching the path of intercepted requests. **Default:** `false`.
|
|
|
|
### `mockPool.intercept(options)`
|
|
|
|
<!-- YAML
|
|
added: v4.0.0
|
|
-->
|
|
|
|
* `options` {MockPoolInterceptOptions} The matching criteria for the requests to
|
|
intercept.
|
|
* Returns: {MockInterceptor} The interceptor used to define the mocked reply.
|
|
|
|
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` |
|
|
|
|
#### Parameter: `MockPoolInterceptOptions`
|
|
|
|
* `path` {string|RegExp|Function} A matcher for the HTTP request path. The
|
|
function form has the signature `(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`.
|
|
* `method` {string|RegExp|Function} A matcher for the HTTP request method. The
|
|
function form has the signature `(method: string) => boolean`.
|
|
**Default:** `'GET'`.
|
|
* `body` {string|RegExp|Function} A matcher for the HTTP request body. The
|
|
function form has the signature `(body: string) => boolean`.
|
|
* `headers` {Object|Function} A matcher for the HTTP request headers, given
|
|
either as a map of header name to a `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.
|
|
* `query` {Object} A matcher for the HTTP request query string parameters. Only
|
|
applies when a `string` was provided for `path`.
|
|
* `ignoreTrailingSlash` {boolean} Whether a trailing slash on `path` is ignored
|
|
when matching. Inherited from the mock pool's `ignoreTrailingSlash` option
|
|
when not set.
|
|
|
|
#### Return: `MockInterceptor`
|
|
|
|
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.
|
|
* `statusCode` {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 and `Buffer`s are sent as-is. The
|
|
function form has the signature
|
|
`(opts: MockResponseCallbackOptions) => string | Buffer | Object` and 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.
|
|
* `callback` {Function} A `(opts: MockResponseCallbackOptions) =>
|
|
{ statusCode, data, responseOptions }` function invoked with the incoming
|
|
request. The callback may be asynchronous; a returned promise is awaited
|
|
and must resolve to the same shape.
|
|
* Returns: {MockScope}
|
|
* `replyWithError(error)` {Function} Defines an error for a matching request to
|
|
throw.
|
|
* `error` {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.
|
|
* `headers` {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.
|
|
* `trailers` {Object} A map of trailer name to value.
|
|
* Returns: {MockInterceptor}
|
|
* `replyContentLength()` {Function} Sets an automatically calculated
|
|
`content-length` header 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`][].
|
|
|
|
#### Parameter: `MockResponseCallbackOptions`
|
|
|
|
The argument passed to the `reply()` data and options callbacks.
|
|
|
|
* `path` {string} The path of the intercepted request.
|
|
* `method` {string} The method of the intercepted request.
|
|
* `headers` {Object|Headers} The headers of the intercepted request.
|
|
* `origin` {string} The origin of the intercepted request.
|
|
* `body` {string|null} The body of the intercepted request.
|
|
|
|
#### Parameter: `MockResponseOptions`
|
|
|
|
* `headers` {Object} Headers to include on the mocked reply.
|
|
* `trailers` {Object} Trailers to include on the mocked reply.
|
|
|
|
#### Return: `MockScope`
|
|
|
|
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.
|
|
* `waitInMs` {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 by `persist()`.
|
|
* `repeatTimes` {number} The number of matching requests the reply applies to.
|
|
* Returns: {MockScope}
|
|
|
|
The following examples show common interception patterns.
|
|
|
|
```mjs displayName="Basic mocked request"
|
|
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
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Reply with a data callback"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({
|
|
path: '/echo',
|
|
method: 'GET'
|
|
}).reply(200, ({ headers }) => ({ message: headers.message }))
|
|
|
|
const { statusCode, body } = await request('http://localhost:3000/echo', {
|
|
headers: { message: 'hello world!' }
|
|
})
|
|
|
|
console.log('response received', statusCode) // response received 200
|
|
|
|
for await (const data of body) {
|
|
console.log('data', data.toString('utf8')) // {"message":"hello world!"}
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Reply with an options callback"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({
|
|
path: '/echo',
|
|
method: 'GET'
|
|
}).reply(({ headers }) => ({
|
|
statusCode: 200,
|
|
data: { message: headers.message }
|
|
}))
|
|
|
|
const { statusCode, body } = await request('http://localhost:3000/echo', {
|
|
headers: { message: 'hello world!' }
|
|
})
|
|
|
|
console.log('response received', statusCode) // response received 200
|
|
|
|
for await (const data of body) {
|
|
console.log('data', data.toString('utf8')) // {"message":"hello world!"}
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Reply with an asynchronous options callback"
|
|
import { readFile } from 'node:fs/promises'
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({
|
|
path: '/fixture',
|
|
method: 'GET'
|
|
}).reply(async ({ path }) => ({
|
|
statusCode: 200,
|
|
data: await readFile(new URL('./fixture.json', import.meta.url))
|
|
}))
|
|
|
|
const { statusCode, body } = await request('http://localhost:3000/fixture')
|
|
|
|
console.log('response received', statusCode) // response received 200
|
|
|
|
for await (const data of body) {
|
|
console.log('data', data.toString('utf8')) // contents of fixture.json
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Multiple intercepts"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo')
|
|
mockPool.intercept({ path: '/hello', method: 'GET' }).reply(200, 'hello')
|
|
|
|
const fooResult = await request('http://localhost:3000/foo')
|
|
for await (const data of fooResult.body) {
|
|
console.log('data', data.toString('utf8')) // data foo
|
|
}
|
|
|
|
const helloResult = await request('http://localhost:3000/hello')
|
|
for await (const data of helloResult.body) {
|
|
console.log('data', data.toString('utf8')) // data hello
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Match query, body, request headers; reply with headers and trailers"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({
|
|
path: '/foo?hello=there&see=ya',
|
|
method: 'POST',
|
|
body: 'form1=data1&form2=data2',
|
|
headers: {
|
|
'User-Agent': 'undici',
|
|
Host: 'example.com'
|
|
}
|
|
}).reply(200, { foo: 'bar' }, {
|
|
headers: { 'content-type': 'application/json' },
|
|
trailers: { 'Content-MD5': 'test' }
|
|
})
|
|
|
|
const { statusCode, headers, trailers, body } = await request(
|
|
'http://localhost:3000/foo?hello=there&see=ya',
|
|
{
|
|
method: 'POST',
|
|
body: 'form1=data1&form2=data2',
|
|
headers: {
|
|
foo: 'bar',
|
|
'User-Agent': 'undici',
|
|
Host: 'example.com'
|
|
}
|
|
}
|
|
)
|
|
|
|
console.log('response received', statusCode) // response received 200
|
|
console.log('headers', headers) // { 'content-type': 'application/json' }
|
|
|
|
for await (const data of body) {
|
|
console.log('data', data.toString('utf8')) // {"foo":"bar"}
|
|
}
|
|
|
|
console.log('trailers', trailers) // { 'content-md5': 'test' }
|
|
```
|
|
|
|
```mjs displayName="Different matcher forms"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({
|
|
path: '/foo',
|
|
method: /^GET$/,
|
|
body: (value) => value === 'form=data',
|
|
headers: {
|
|
'User-Agent': 'undici',
|
|
Host: /^example\.com$/
|
|
}
|
|
}).reply(200, 'foo')
|
|
|
|
const { statusCode, body } = await request('http://localhost:3000/foo', {
|
|
method: 'GET',
|
|
body: 'form=data',
|
|
headers: {
|
|
foo: 'bar',
|
|
'User-Agent': 'undici',
|
|
Host: 'example.com'
|
|
}
|
|
})
|
|
|
|
console.log('response received', statusCode) // response received 200
|
|
|
|
for await (const data of body) {
|
|
console.log('data', data.toString('utf8')) // data foo
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Reply with an error"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({
|
|
path: '/foo',
|
|
method: 'GET'
|
|
}).replyWithError(new Error('kaboom'))
|
|
|
|
try {
|
|
await request('http://localhost:3000/foo', { method: 'GET' })
|
|
} catch (error) {
|
|
console.error(error.message) // kaboom
|
|
}
|
|
```
|
|
|
|
```mjs displayName="Default reply headers"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo', method: 'GET' })
|
|
.defaultReplyHeaders({ foo: 'bar' })
|
|
.reply(200, 'foo')
|
|
|
|
const { headers } = await request('http://localhost:3000/foo')
|
|
|
|
console.log('headers', headers) // headers { foo: 'bar' }
|
|
```
|
|
|
|
```mjs displayName="Default reply trailers"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo', method: 'GET' })
|
|
.defaultReplyTrailers({ foo: 'bar' })
|
|
.reply(200, 'foo')
|
|
|
|
const { trailers } = await request('http://localhost:3000/foo')
|
|
|
|
console.log('trailers', trailers) // trailers { foo: 'bar' }
|
|
```
|
|
|
|
```mjs displayName="Automatic content-length"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo', method: 'GET' })
|
|
.replyContentLength()
|
|
.reply(200, 'foo')
|
|
|
|
const { headers } = await request('http://localhost:3000/foo')
|
|
|
|
console.log('headers', headers) // headers { 'content-length': '3' }
|
|
```
|
|
|
|
```mjs displayName="Persisted reply"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo').persist()
|
|
|
|
await request('http://localhost:3000/foo') // Matches and returns the mock
|
|
await request('http://localhost:3000/foo') // Matches again, indefinitely
|
|
```
|
|
|
|
```mjs displayName="Reply a fixed number of times"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo').times(2)
|
|
|
|
await request('http://localhost:3000/foo') // Matches and returns the mock
|
|
await request('http://localhost:3000/foo') // Matches and returns the mock
|
|
await request('http://localhost:3000/foo') // No match; a real request is attempted
|
|
```
|
|
|
|
```mjs displayName="Match the path with a function"
|
|
import { MockAgent, setGlobalDispatcher, request } from 'undici'
|
|
import querystring from 'node:querystring'
|
|
|
|
const mockAgent = new MockAgent()
|
|
setGlobalDispatcher(mockAgent)
|
|
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
const matchPath = (requestPath) => {
|
|
const [pathname, search] = requestPath.split('?')
|
|
const requestQuery = querystring.parse(search)
|
|
|
|
if (!pathname.startsWith('/foo')) {
|
|
return false
|
|
}
|
|
|
|
return requestQuery.foo === 'bar'
|
|
}
|
|
|
|
mockPool.intercept({ path: matchPath, method: 'GET' }).reply(200, 'foo')
|
|
|
|
await request('http://localhost:3000/foo?foo=bar') // Matches and returns the mock
|
|
```
|
|
|
|
### `mockPool.close()`
|
|
|
|
<!-- YAML
|
|
added: v4.0.0
|
|
-->
|
|
|
|
* Returns: {Promise} Fulfills with `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`][].
|
|
|
|
```mjs
|
|
import { MockAgent } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
await mockPool.close()
|
|
```
|
|
|
|
### `mockPool.dispatch(options, handlers)`
|
|
|
|
<!-- YAML
|
|
added: v4.0.0
|
|
-->
|
|
|
|
* `options` {DispatchOptions} The request options.
|
|
* `handlers` {DispatchHandler} The handlers invoked over the request lifecycle.
|
|
* Returns: {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])`
|
|
|
|
<!-- YAML
|
|
added: v4.0.0
|
|
-->
|
|
|
|
* `options` {DispatchOptions}
|
|
* `callback` {Function} (optional) Invoked with the response when no `Promise`
|
|
is requested.
|
|
* Returns: {Promise} Fulfills with the mocked response when no `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.
|
|
|
|
```mjs
|
|
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()`
|
|
|
|
<!-- YAML
|
|
added: v7.11.0
|
|
-->
|
|
|
|
* Returns: {undefined}
|
|
|
|
Removes all registered interceptors from the mock pool. Pending mocks defined
|
|
before this call no longer match incoming requests.
|
|
|
|
```mjs
|
|
import { MockAgent } from 'undici'
|
|
|
|
const mockAgent = new MockAgent()
|
|
const mockPool = mockAgent.get('http://localhost:3000')
|
|
|
|
mockPool.intercept({ path: '/foo' }).reply(200, 'foo')
|
|
mockPool.cleanMocks()
|
|
```
|
|
|
|
[`MockAgent`]: MockAgent.md#class-mockagent
|
|
[`MockClient`]: MockClient.md#class-mockclient
|
|
[`MockInterceptor`]: MockPool.md#return-mockinterceptor
|
|
[`MockScope`]: MockPool.md#return-mockscope
|
|
[`Pool`]: Pool.md#class-pool
|
|
[`dispatcher.dispatch(options, handlers)`]: Dispatcher.md#dispatcherdispatchoptions-handler
|
|
[`dispatcher.request(options[, callback])`]: Dispatcher.md#dispatcherrequestoptions-callback
|
|
[`mockAgent.get(origin)`]: MockAgent.md#mockagentgetorigin
|