egg-mock
Mock library for testing Egg applications, plugins and custom Egg frameworks with ease. egg-mock
inherits all APIs from node_modules/mm, offering more flexibility.
Install
$ npm i egg-mock --save-dev
Usage
Create testcase
Launch a mock server with mm.app
const path = require('path');
const mm = require('egg-mock');
describe('some test', () => {
let app;
before(() => {
app = mm.app({
baseDir: 'apps/foo'
});
return app.ready();
})
after(() => app.close());
it('should request /', () => {
return app.httpRequest()
.get('/')
.expect(200);
});
});
Retrieve Agent instance through app.agent
after mm.app
started.
Using mm.cluster
launch cluster server, you can use the same API as mm.app
;
Test Application
baseDir
is optional that is process.cwd()
by default.
before(() => {
app = mm.app();
return app.ready();
});
Test Framework
framework is optional, it's node_modules/egg
by default.
before(() => {
app = mm.app({
baseDir: 'apps/demo',
framework: true,
});
return app.ready();
});
Test Plugin
If eggPlugin.name
is defined in package.json
, it's a plugin that will be loaded to plugin list automatically.
before(() => {
app = mm.app({
baseDir: 'apps/demo',
});
return app.ready();
});
You can also test the plugin in different framework, e.g. test aliyun-egg and framework-b in one plugin.
describe('aliyun-egg', () => {
let app;
before(() => {
app = mm.app({
baseDir: 'apps/demo',
framework: path.join(__dirname, 'node_modules/aliyun-egg'),
});
return app.ready();
});
});
describe('framework-b', () => {
let app;
before(() => {
app = mm.app({
baseDir: 'apps/demo',
framework: path.join(__dirname, 'node_modules/framework-b'),
});
return app.ready();
});
});
If it's detected as an plugin, but you don't want it to be, you can use plugin = false
.
before(() => {
app = mm.app({
baseDir: 'apps/demo',
plugin: false,
});
return app.ready();
});
API
mm.app(options)
Create a mock application.
mm.cluster(options)
Create a mock cluster server, but you can't use API in application, you should test using supertest
.
const mm = require('egg-mock');
describe('test/app.js', () => {
let app, config;
before(() => {
app = mm.cluster();
return app.ready();
});
after(() => app.close());
it('some test', () => {
return app.httpRequest()
.get('/config')
.expect(200)
});
});
You can disable coverage, because it's slow.
mm.cluster({
coverage: false,
});
mm.env(env)
Mock env when starting
mm.env('prod');
mm.app({
cache: false,
});
Environment list https://github.com/eggjs/egg-core/blob/master/lib/loader/egg_loader.js#L82
mm.consoleLevel(level)
Mock level that print to stdout/stderr
mm.consoleLevel('NONE');
level list: DEBUG
, INFO
, WARN
, ERROR
, NONE
mm.home(homePath)
mock home directory
mm.restore()
restore all mock data, e.g. afterEach(mm.restore)
options
Options for mm.app
and mm.cluster
baseDir {String}
The directory of application, default is process.cwd()
.
mm.app({
baseDir: path.join(__dirname, 'fixtures/apps/demo'),
})
You can use a string based on $CWD/test/fixtures
for short
mm.app({
baseDir: 'apps/demo',
})
framework {String/Boolean}
The directory of framework
mm.app({
baseDir: 'apps/demo',
framework: path.join(__dirname, 'fixtures/egg'),
})
It can be true when test an framework
plugin
The directory of plugin, it's detected automatically.
mm.app({
baseDir: 'apps/demo',
})
plugins {Object}
Define a list of plugins
cache {Boolean}
Determine whether enable cache. it's cached by baseDir.
clean {Boolean}
Clean all logs directory, default is true.
If you are using ava
, disable it.
app.mockLog([logger]) and app.expectLog(str[, logger]), app.notExpectLog(str[, logger])
Assert some string value in the logger instance.
It is recommended to pair app.mockLog()
with app.expectLog()
or app.notExpectLog()
.
Using app.expectLog()
or app.notExpectLog()
alone requires dependency on the write speed of the log. When the server disk is high IO, unstable results will occur.
it('should work', async () => {
app.mockLog();
await app.httpRequest()
.get('/')
.expect('hello world')
.expect(200);
app.expectLog('foo in logger');
app.expectLog('foo in coreLogger', 'coreLogger');
app.expectLog('foo in myCustomLogger', 'myCustomLogger');
app.notExpectLog('bar in logger');
app.notExpectLog('bar in coreLogger', 'coreLogger');
app.notExpectLog('bar in myCustomLogger', 'myCustomLogger');
});
app.httpRequest()
Request current app http server.
it('should work', () => {
return app.httpRequest()
.get('/')
.expect('hello world')
.expect(200);
});
See supertest to get more APIs.
Assert current response not contains the specified header
it('should work', () => {
return app.httpRequest()
.get('/')
.unexpectHeader('set-cookie')
.expect(200);
});
Assert current response contains the specified header
it('should work', () => {
return app.httpRequest()
.get('/')
.expectHeader('set-cookie')
.expect(200);
});
app.mockContext(options)
const ctx = app.mockContext({
user: {
name: 'Jason'
}
});
console.log(ctx.user.name);
app.mockCookies(data)
app.mockCookies({
foo: 'bar'
});
const ctx = app.mockContext();
console.log(ctx.getCookie('foo'));
Mock request header
app.mockSession(data)
app.mockSession({
foo: 'bar'
});
const ctx = app.mockContext();
console.log(ctx.session.foo);
app.mockService(service, methodName, fn)
it('should mock user name', function* () {
app.mockService('user', 'getName', function* (ctx, methodName, args) {
return 'popomore';
});
const ctx = app.mockContext();
yield ctx.service.user.getName();
});
app.mockServiceError(service, methodName, error)
You can mock an error for service
app.mockServiceError('user', 'home', new Error('mock error'));
app.mockCsrf()
app.mockCsrf();
return app.httpRequest()
.post('/login')
.expect(302);
app.mockHttpclient(url, method, data)
Mock httpclient request, e.g.: ctx.curl
app.get('/', function*() {
const ret = yield this.curl('https://eggjs.org');
this.body = ret.data.toString();
});
app.mockHttpclient('https://eggjs.org', {
data: 'mock egg',
});
return app.httpRequest()
.post('/')
.expect('mock egg');
You can also use Regular Expression for matching url.
app.mockHttpclient(/\/users\/[a-z]$/i, {
data: {
name: 'egg',
},
});
You can alse mock agent.httpclient
app.agent.mockHttpclient('https://eggjs.org', {
data: {
name: 'egg',
},
});
Bootstrap
We also provide a bootstrap file for applications' unit test to reduce duplicated code:
const { app, mock, assert } = require('egg-mock/bootstrap');
describe('test app', () => {
it('should request success', () => {
mock.data(app, 'method', { foo: 'bar' });
return app.httpRequest()
.get('/foo')
.expect(res => {
assert(!res.headers.foo);
})
.expect(/bar/);
});
});
Questions & Suggestions
Please open an issue here.
License
MIT
Contributors