Egg provides a dedicated mocking helper package for application unit tests: @eggjs/mock (historically known as egg-mock).
- Repository (Egg 3.x / egg-mock@5.x, peerDependencies.egg: ^3.12.0): https://github.com/eggjs/mock/tree/5.x
- API reference: see README in the repo.
@eggjs/mock is built on top of mm (Mock Mate), which provides low-level monkey-patching utilities.
- Repository: https://github.com/node-modules/mm
Install
npm i @eggjs/mock --save-devIn many docs / legacy code you may still see
egg-mock. For Egg 3.x, the recommended package name is@eggjs/mock.
Quick Start
Create an app instance
const mock = require('@eggjs/mock');
describe('test/controller/home.test.js', () => {
let app;
before(async () => {
app = mock.app({ baseDir: 'path/to/your/app' });
await app.ready();
});
after(() => app.close());
});Use bootstrap to avoid repeated setup
const { app, mock, assert } = require('egg-mock/bootstrap');
describe('test/controller/home.test.js', () => {
// test cases
});The bootstrap helper wires common setup/teardown and is convenient for most projects.
Create a Context
it('should get a ctx', () => {
const ctx = app.mockContext();
assert(ctx.method === 'GET');
});
it('should mock ctx.user', () => {
const ctx = app.mockContext({
user: { name: 'fengmk2' },
});
assert(ctx.user.name === 'fengmk2');
});Restore after each test
When using mm / @eggjs/mock, remember to restore mocked state:
const mm = require('mm');
afterEach(() => mm.restore());If you use egg-mock/bootstrap, it already restores mocks for you in afterEach.
mm (Mock Mate) API
mm is a general purpose monkey-patching library. @eggjs/mock is built on top of it, and many Egg tests use mm directly.
Prefer using @eggjs/mock exports
For consistency inside the Egg ecosystem, prefer the mm that is exported by @eggjs/mock (egg-mock). It is compatible with mm and adds Egg-specific helpers.
// CJS
const { app, mm } = require('egg-mock/bootstrap');
// mm.restore() in afterEach is already wired by bootstrap
// or
const mock = require('@eggjs/mock');
mock(target, 'prop', value);
mock.restore();You can still use the standalone mm package directly if needed:
import mm, { restore } from 'mm';Core
mm(target, property, value)/mm.mock(...): monkey-patch a property.mm.restore()/restore(): restore all patched properties.mm.isMocked(target, property): check if a property is mocked.mm.spy(target, method): spy a function (records call counts/args).
When a mocked property is a function, mm will attach spy fields like
called,calledArguments,lastCalledArguments.
Callback-style helpers
mm.data(target, method, data[, timeout]): callback returns(null, data).mm.datas(target, method, datas[, timeout]): callback returns(null, ...datas).mm.empty(target, method[, timeout]): callback returns(null, null).mm.error(target, method, error[, props|timeout][, timeout]): callback returns an error.mm.errorOnce(...): likeerrorbut only once.
Sync helpers
mm.syncData(target, method, value): return value.mm.syncEmpty(target, method): returnundefined.mm.syncError(target, method, error[, props]): throw error.
HTTP helpers
mm.http.request(url, data[, headers][, delay]): mockhttp.request/http.get.mm.http.requestError(url[, reqError][, resError][, delay]): mock request/response errors.mm.https.request(...)/mm.https.requestError(...): same for https.
Other
mm.spawn(code, stdout, stderr[, timeout]): mockchild_process.spawn.mm.classMethod(instance, method, mockFn): mock a class method via prototype.
For complete and up-to-date details, see the mm repository: https://github.com/node-modules/mm