Detalhes do pacote

mm

node-modules92.5kMIT4.0.2

mock mate, mock http request, fs access and so on.

mm, muk, mock, test

readme (leia-me)

mm, mock mate

NPM version Node.js CI Test coverage npm download Node.js Version

An simple but flexible mock(or say stub) package, mock mate.

Install

npm install mm --save-dev

Usage

import fs from 'node:fs';
import { mm } from 'mm';

mm(fs, 'readFileSync', function(filename) {
  return filename + ' content';
});

console.log(fs.readFileSync('《九评 Java》'));
// => 《九评 Java》 content

restore();
console.log(fs.readFileSync('《九评 Java》'));
// => throw `Error: ENOENT, no such file or directory '《九评 Java》`

Support spy

If mocked property is a function, it will be spied, every time it called, mm will modify .called, .calledArguments and .lastCalledArguments. For example:

import { mm } from 'mm';

const target = {
  async add(a, b) {
    return a + b;
  },
};

mm.data(target, 'add', 3);

assert.equal(await target.add(1, 1), 3);
assert.equal(target.add.called, 1);
assert.deepEqual(target.add.calledArguments, [[ 1, 1 ]]);
assert.deepEqual(target.add.lastCalledArguments, [ 1, 1 ]);

assert.equal(await target.add(2, 2), 3);
assert.equal(target.add.called, 2);
assert.deepEqual(target.add.calledArguments, [[ 1, 1 ], [ 2, 2 ]]);
assert.deepEqual(target.add.lastCalledArguments, [ 2, 2 ]);

If you only need spy and don't need mock, you can use mm.spy method directly:

import { mm } from 'mm';

const target = {
  async add(a, b) {
    await this.foo();
    return a + b;
  },
  async foo() { /* */ },
};

mm.spy(target, 'add');
assert.equal(await target.add(1, 1), 2);
assert.equal(target.add.called, 1);
assert.deepEqual(target.add.calledArguments, [[ 1, 1 ]]);
assert.deepEqual(target.add.lastCalledArguments, [ 1, 1 ]);

assert.equal(await target.add(2, 2), 4);
assert.equal(target.add.called, 2);
assert.deepEqual(target.add.calledArguments, [[ 1, 1 ], [ 2, 2 ]]);
assert.deepEqual(target.add.lastCalledArguments, [ 2, 2 ]);

API

.error(module, propertyName, errerMessage, errorProperties)

import fs from 'node:fs';
import { mm } from 'mm';

mm.error(fs, 'readFile', 'mock fs.readFile return error');

fs.readFile('/etc/hosts', 'utf8', function (err, content) {
  // err.name === 'MockError'
  // err.message === 'mock fs.readFile return error'
  console.log(err);

  mm.restore(); // remove all mock effects.

  fs.readFile('/etc/hosts', 'utf8', function (err, content) {
    console.log(err); // => null
    console.log(content); // => your hosts
  });
});

.errorOnce(module, propertyName, errerMessage, errorProperties)

Just like mm.error(), but only mock error once.

import fs from 'node:fs';
import { mm } from 'mm';

mm.errorOnce(fs, 'readFile', 'mock fs.readFile return error');

fs.readFile('/etc/hosts', 'utf8', function (err, content) {
  // err.name === 'MockError'
  // err.message === 'mock fs.readFile return error'
  console.log(err);

  fs.readFile('/etc/hosts', 'utf8', function (err, content) {
    console.log(err); // => null
    console.log(content); // => your hosts
  });
});

.data(module, propertyName, secondCallbackArg)

mm.data(fs, 'readFile', Buffer.from('some content'));

// equals

fs.readFile = function (...args, callback) {
  callback(null, Buffer.from('some content'))
};

.dataWithAsyncDispose(module, propertyName, promiseResolveArg)

Support Symbol.asyncDispose

mm.dataWithAsyncDispose(locker, 'tryLock', {
  locked: true,
});

// equals

locker.tryLock = async () => {
  return {
    locked: true,
    [Symbol.asyncDispose](): async () => {
      // do nothing
    },
  };
}

Run test with await using should work:

mm.dataWithAsyncDispose(locker, 'tryLock', {
  locked: true,
});

await using lock = await locker.tryLock('foo-key');
assert.equal(lock.locked, true);

.empty(module, propertyName)

mm.empty(mysql, 'query');

// equals

mysql.query = function (...args, callback) {
  callback();
}

.datas(module, propertyName, argsArray)

mm.datas(urllib, 'request', [Buffer.from('data'), {headers: { foo: 'bar' }}]);

// equals

urllib.request = function (...args, callback) {
  callback(null, Buffer.from('data'), {headers: { foo: 'bar' }});
}

.syncError(module, propertyName, errerMessage, errorProperties)

var { mm } = require('mm');
var fs = require('fs');

mm.syncError(fs, 'readFileSync', 'mock fs.readFile return error', {code: 'ENOENT'});

// equals

fs.readFileSync = function (...args) {
  var err = new Error('mock fs.readFile return error');
  err.code = 'ENOENT';
  throw err;
};

.syncData(module, propertyName, value)

mm.syncData(fs, 'readFileSync', Buffer.from('some content'));

// equals

fs.readFileSync = function (...args) {
  return Buffer.from('some content');
};

.syncEmpty

mm.syncEmpty(fs, 'readFileSync');

// equals

fs.readFileSync = function (...args) {
  return;
}

.restore()

// restore all mock properties
mm.restore();

.http.request(mockUrl, mockResData, mockResHeaders) and .https.request(mockUrl, mockResData, mockResHeaders)

var { mm } = require('mm');
var http = require('http');

var mockURL = '/foo';
var mockResData = 'mock data';
var mockResHeaders = { server: 'mock server' };
mm.http.request(mockURL, mockResData, mockResHeaders);
mm.https.request(mockURL, mockResData, mockResHeaders);

// http
http.get({
  path: '/foo'
}, function (res) {
  console.log(res.headers); // should be mock headers
  var body = '';
  res.on('data', function (chunk) {
    body += chunk.toString();
  });
  res.on('end', function () {
    console.log(body); // should equal 'mock data'
  });
});

// https
https.get({
  path: '/foo'
}, function (res) {
  console.log(res.headers); // should be mock headers
  var body = '';
  res.on('data', function (chunk) {
    body += chunk.toString();
  });
  res.on('end', function () {
    console.log(body); // should equal 'mock data'
  });
});

.http.requestError(mockUrl, reqError, resError) and .https.requestError(mockUrl, reqError, resError)

var { mm } = require('mm');
var http = require('http');

var mockURL = '/foo';
var reqError = null;
var resError = 'mock res error';
mm.http.requestError(mockURL, reqError, resError);

var req = http.get({
  path: '/foo'
}, function (res) {
  console.log(res.statusCode, res.headers); // 200 but never emit `end` event
  res.on('end', fucntion () {
    console.log('never show this message');
  });
});
req.on('error', function (err) {
  console.log(err); // should return mock err: err.name === 'MockHttpResponseError'
});

.classMethod(instance, method, mockMethod)

class Foo {
  async fetch() {
    return 1;
  }
}

const foo = new Foo();
const foo1 = new Foo();

mm.classMethod(foo, 'fetch', async () => {
  return 3;
});
assert(await foo.fetch() === 3);
assert(await foo1.fetch() === 3);

License

MIT

Contributors

Contributors

Made with contributors-img.

changelog (log de mudanças)

Changelog

4.0.2 (2025-01-02)

Bug Fixes

  • allow call mm.restore on normal export (#63) (18f4f7c)

4.0.1 (2024-12-21)

Bug Fixes

4.0.0 (2024-12-20)

⚠ BREAKING CHANGES

  • drop Node.js < 18.19.0 support

part of https://github.com/eggjs/egg/issues/3644

https://github.com/eggjs/egg/issues/5257

Features

  • support cjs and esm both by tshy (#61) (f1eadcc)

3.4.0 (2023-12-09)

Features

  • support mock.dataWithAsyncDispose() (#59) (7581288)

3.3.0 (2023-05-16)

Features

3.2.4 (2023-05-16)

Bug Fixes

3.2.3 (2023-05-12)

Bug Fixes

3.2.2 (2023-04-02)

Bug Fixes

  • spy statistics is not reset after restore (#55) (97dcf42)

3.2.1 / 2022-11-20

fixes

3.2.0 / 2020-03-24

features

3.1.0 / 2020-03-13

features

3.0.3 / 2020-03-12

fixes

3.0.2 / 2020-03-01

fixes

3.0.1 / 2020-03-01

fixes

3.0.0 / 2020-03-01

features

others

2.5.0 / 2019-03-06

features

others

2.4.1 / 2018-08-27

fixes

2.4.0 / 2018-08-08

others

2.3.0 / 2018-08-07

features

2.2.2 / 2018-07-12

fixes

2.2.1 / 2018-07-11

fixes

2.2.0 / 2017-09-07

features

others

2.1.1 / 2017-09-06

fixes

others

2.1.0 / 2017-01-25

  • deps: use muk-prop instead of muk (#30)

2.0.1 / 2017-01-22

  • fix: Only restore the http/https request when used.

2.0.0 / 2016-07-31

  • feat: upgrade dependencies (#29)

1.5.1 / 2016-07-21

  • fix: keep status code (#28)

1.5.0 / 2016-06-13

  • feat: export isMocked (#27)

1.4.0 / 2016-06-12

  • deps: upgrade muk (#26)
  • feat: remove EventEmitter from 'event' module

1.3.5 / 2015-09-29

  • fix: should support mock multi env

1.3.4 / 2015-09-24

  • test: use codecov.io
  • feat: support mock process.env.KEY

1.3.3 / 2015-09-17

  • deps: upgrade muk to 0.4.0 to support mock getter

1.3.2 / 2015-09-17

  • fix: deps muk 0.3.2

1.3.1 / 2015-08-31

  • hotfix: fix mm.error in es6

1.3.0 / 2015-08-22

  • readme: add sync methods and error properties
  • feat: mock error support props
  • chore: use npm scripts

1.2.0 / 2015-08-16

  • feat(sync): add sync mock methods

1.1.0 / 2015-05-08

  • feat: support promise

1.0.1 / 2014-10-30

  • still thunkify the methods

1.0.0 / 2014-10-30

  • docs(readme): add badges
  • feat(error): support mock error on generator function
  • feat(data): support mock generator function

0.2.1 / 2014-03-14

  • if coveralls crash, dont break the test pass
  • fix http request mock not work on 0.11.12 and no more test on 0.8.x

0.2.0 / 2014-02-21

  • support thunkify cnpm/cnpmjs.org#196

0.1.8 / 2013-12-27

  • fix Node 0.11 broken. (@alsotang)
  • fix test cases

0.1.7 / 2013-11-20

  • http.request mock support mm.http.request({host: $host, url: $url})
  • add npm image

0.1.6 / 2013-07-04

0.1.5 / 2013-07-03

  • hot fixed #5 mock same method twices restore fails bug
  • add test for fs.readFileSync. fixed #5
  • support coveralls

0.1.4 / 2013-05-21

  • use blanket instead of jscover
  • fixed spawn test fail on node 0.6
  • support emtpy error

0.1.3 / 2013-05-05

  • Merge pull request #3 from dead-horse/support-spawn
  • do not emit when null
  • add support for spawn

0.1.2 / 2013-04-20

  • fix mm.datas
  • update travis

0.1.1 / 2013-04-15

  • update muk to 0.3.0+

0.1.0 / 2012-12-01

  • fixed restore not effect on http(s)

0.0.9 / 2012-11-28

  • add request() mock statusCode

0.0.8 / 2012-11-27

  • add mm.datas(), mm.data(), mm.empty() mock methods

0.0.7 / 2012-11-26

  • try to find callback in arguments
  • fixed CERT_HAS_EXPIRED with rejectUnauthorized = false

0.0.6 / 2012-11-21

  • fix http.request() twice bug; add res.setEncoding method

0.0.5 / 2012-11-21

  • fixed #1 support mm.https.request mock helpers

0.0.4 / 2012-11-13

  • add mm() just like muk() does

0.0.3 / 2012-11-06

  • add req.abort() for mock request object

0.0.2 / 2012-11-06

  • when mock response error, must emit req error not res error event.
  • replace logo

0.0.1 / 2012-11-04

  • add mock http.request() and http.requestError()
  • add mm.error() impl
  • Release 0.0.1