zero-to-one-mock
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

egg-mock

NPM version build status Test coverage David deps Known Vulnerabilities npm download

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

// test/index.test.js
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

// production environment
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.httpRequest()

Request current app http server.

it('should work', () => {
  return app.httpRequest()
    .get('/')
    .expect('hello world')
    .expect(200);
});

See supertest to get more APIs.

app.mockContext(options)

const ctx = app.mockContext({
  user: {
    name: 'Jason'
  }
});
console.log(ctx.user.name); // Jason

app.mockCookies(data)

app.mockCookies({
  foo: 'bar'
});
const ctx = app.mockContext();
console.log(ctx.getCookie('foo'));

app.mockHeaders(data)

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', {
  // can be buffer / string / json,
  // will auto convert to buffer
  // follow options.dataType to convert
  data: 'mock egg',
});
// app.mockHttpclient('https://eggjs.org', 'get', mockResponse); // mock get
// app.mockHttpclient('https://eggjs.org', [ 'get' , 'head' ], mockResponse); // mock get and head
// app.mockHttpclient('https://eggjs.org', '*', mockResponse); // mock all methods
// app.mockHttpclient('https://eggjs.org', mockResponse); // mock all methods by default

return app.httpRequest()
  .post('/')
  .expect('mock 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 will be restored each case
    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

Dependencies (0)

    Dev Dependencies (0)

      Package Sidebar

      Install

      npm i zero-to-one-mock

      Weekly Downloads

      0

      Version

      1.0.0

      License

      ISC

      Last publish

      Collaborators

      • lovelife10000