Needlessly Provoking Marsupials

    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

    Keywords

    none

    Install

    npm i zero-to-one-mock

    DownloadsWeekly Downloads

    2

    Version

    1.0.0

    License

    ISC

    Last publish

    Collaborators

    • lovelife10000