Skip to content

Commit

Permalink
feat: support mock error once (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Mar 6, 2019
1 parent 2cb2baf commit c204c5e
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 78 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -5,6 +5,7 @@ node_js:
- '6'
- '8'
- '10'
- '11'
install:
- npm i npminstall && npminstall
script:
Expand Down
24 changes: 23 additions & 1 deletion README.md
Expand Up @@ -87,6 +87,28 @@ fs.readFile('/etc/hosts', 'utf8', function (err, content) {
});
```

### .errorOnce(module, propertyName, errerMessage, errorProperties)

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

```js
const mm = require('mm');
const fs = require('fs');

mm.errorOne(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)

```js
Expand Down Expand Up @@ -234,7 +256,7 @@ var req = http.get({
});
req.on('error', function (err) {
console.log(err); // should return mock err: err.name === 'MockHttpResponseError'
}
});
```

## License
Expand Down
39 changes: 35 additions & 4 deletions azure-pipelines.template.yml
Expand Up @@ -2,21 +2,52 @@
# Build a general Node.js application with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/vsts/pipelines/languages/javascript
# demo: https://github.com/ryanelian/instapack/blob/master/azure-pipelines.template.yml
# demo: https://github.com/parcel-bundler/parcel/blob/master/azure-pipelines-template.yml

jobs:
- job: ${{ parameters.name }}
pool:
vmImage: ${{ parameters.vmImage }}
strategy:
matrix:
node_4:
node_version: 4
node_6:
node_version: 6
node_8:
node_version: 8
node_10:
node_version: 10
node_11:
node_version: 11
maxParallel: 5
steps:
- task: NodeTool@0
inputs:
versionSpec: ${{ parameters.node_version }}
versionSpec: $(node_version)
displayName: 'Install Node.js'

# Set ENV
- ${{ if ne(parameters.name, 'windows') }}:
- script: |
echo $PWD
export PATH="$PATH:$PWD/node_modules/.bin"
echo "##vso[task.setvariable variable=PATH]$PATH"
displayName: Set ENV
- ${{ if eq(parameters.name, 'windows') }}:
- script: |
echo %cd%
set PATH=%PATH%;%cd%\node_modules\.bin
echo "##vso[task.setvariable variable=PATH]%PATH%"
displayName: Set ENV
- script: |
${{ parameters.install_script }}
npm i npminstall && npminstall
displayName: 'Install Packages'
- script: |
${{ parameters.test_script }}
npm run ci
displayName: 'Build & Unit Test'
- ${{ if ne(parameters.name, 'windows') }}:
- script: |
npminstall codecov && codecov
displayName: 'Report Coverage'
57 changes: 4 additions & 53 deletions azure-pipelines.yml
@@ -1,65 +1,16 @@
jobs:
- template: azure-pipelines.template.yml
parameters:
name: win_node_4
vmImage: 'vs2017-win2016'
node_version: 4
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

- template: azure-pipelines.template.yml
parameters:
name: win_node_6
vmImage: 'vs2017-win2016'
node_version: 6
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'
name: linux
vmImage: 'ubuntu-16.04'

- template: azure-pipelines.template.yml
parameters:
name: win_node_8
name: windows
vmImage: 'vs2017-win2016'
node_version: 8
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

- template: azure-pipelines.template.yml
parameters:
name: win_node_10
vmImage: 'vs2017-win2016'
node_version: 10
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

- template: azure-pipelines.template.yml
parameters:
name: macos_node_4
vmImage: 'xcode9-macos10.13'
node_version: 4
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

- template: azure-pipelines.template.yml
parameters:
name: macos_node_6
vmImage: 'xcode9-macos10.13'
node_version: 6
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

- template: azure-pipelines.template.yml
parameters:
name: macos_node_8
vmImage: 'xcode9-macos10.13'
node_version: 8
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

- template: azure-pipelines.template.yml
parameters:
name: macos_node_10
name: macos
vmImage: 'xcode9-macos10.13'
node_version: 10
install_script: 'npm i -g npminstall && npminstall'
test_script: 'npm run ci'

5 changes: 5 additions & 0 deletions index.d.ts
Expand Up @@ -23,6 +23,11 @@ declare namespace mm {
*/
function error(mod: any, method: string, error?: string | Error, props?: object, timeout?: number): MockMate;

/**
* Mock async function error once.
*/
function errorOnce(mod: any, method: string, error?: string | Error, props?: object, timeout?: number): MockMate;

/**
* mock return callback(null, data).
*/
Expand Down
20 changes: 20 additions & 0 deletions lib/es6.js
Expand Up @@ -49,3 +49,23 @@ mm.error = function(mod, method, error, props, timeout) {
});
return this;
};

const mockErrorOnce = mm.errorOnce;
mm.errorOnce = function(mod, method, error, props, timeout) {
if (!is.generatorFunction(mod[method])) {
return mockErrorOnce.call(mm, mod, method, error, props, timeout);
}

error = mm._createError(error, props);

if (timeout) {
timeout = parseInt(timeout, 10);
}
timeout = timeout || 0;
mm(mod, method, function* () {
yield sleep(timeout);
mm.restore();
throw error;
});
return this;
};
42 changes: 31 additions & 11 deletions lib/mm.js
Expand Up @@ -63,16 +63,7 @@ exports._createError = function(error, props) {
return error;
};

/**
* Mock async function error.
* @param {Object} mod, module object
* @param {String} method, mock module object method name.
* @param {String|Error} error, error string message or error instance.
* @param {Object} props, error properties
* @param {Number} timeout, mock async callback timeout, default is 0.
* @return {mm} this - mm
*/
exports.error = function(mod, method, error, props, timeout) {
exports._mockError = function(mod, method, error, props, timeout, once) {
if (typeof props === 'number') {
timeout = props;
props = {};
Expand All @@ -86,12 +77,41 @@ exports.error = function(mod, method, error, props, timeout) {
mock(mod, method, thenify(function() {
const callback = getCallback(arguments);
setTimeout(function() {
if (once) {
exports.restore();
}
callback(error);
}, timeout);
}));
return this;
};

/**
* Mock async function error.
* @param {Object} mod, module object
* @param {String} method, mock module object method name.
* @param {String|Error} error, error string message or error instance.
* @param {Object} props, error properties
* @param {Number} timeout, mock async callback timeout, default is 0.
* @return {mm} this - mm
*/
exports.error = function(mod, method, error, props, timeout) {
return exports._mockError(mod, method, error, props, timeout);
};

/**
* Mock async function error once.
* @param {Object} mod, module object
* @param {String} method, mock module object method name.
* @param {String|Error} error, error string message or error instance.
* @param {Object} props, error properties
* @param {Number} timeout, mock async callback timeout, default is 0.
* @return {mm} this - mm
*/
exports.errorOnce = function(mod, method, error, props, timeout) {
return exports._mockError(mod, method, error, props, timeout, true);
};

/**
* mock return callback(null, data1, data2).
*
Expand Down Expand Up @@ -316,7 +336,7 @@ function _request(mod, url, data, headers, delay) {

if (!req._aborted) {
if (typeof chunk === 'string') {
chunk = new Buffer(chunk);
chunk = Buffer.from ? Buffer.from(chunk) : new Buffer(chunk);
}
if (this.charset) {
chunk = chunk.toString(this.charset);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -52,7 +52,7 @@
},
"ci": {
"type": "travis, azure-pipelines",
"version": "4, 6, 8, 10"
"version": "4, 6, 8, 10, 11"
},
"author": "fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)",
"license": "MIT"
Expand Down
34 changes: 29 additions & 5 deletions test/es6.js
@@ -1,8 +1,8 @@
'use strict';

const mm = require('../');
const mm = require('..');

describe('test/es6.test.js', function() {
describe('test/es6.test.js', () => {
const foo = {
* getMultiValues() {
return [ 1, 2, 3 ];
Expand All @@ -14,7 +14,7 @@ describe('test/es6.test.js', function() {

afterEach(mm.restore);

describe('datas(), data()', function() {
describe('datas(), data()', () => {
it('should mock generator function', function* () {
let datas;
mm.datas(foo, 'getMultiValues', [ 'b1', 'b2', 'b3' ]);
Expand All @@ -36,11 +36,11 @@ describe('test/es6.test.js', function() {
});
});

describe('error()', function() {
describe('error(), errorOnce()', () => {
it('should mock error', function* () {
mm.error(foo, 'getValue');
try {
yield* foo.getValue();
yield foo.getValue();
throw new Error('should not run this');
} catch (err) {
err.message.should.equal('mm mock error');
Expand Down Expand Up @@ -84,5 +84,29 @@ describe('test/es6.test.js', function() {
use.should.above(90);
}
});

it('should mock error once', function* () {
mm.errorOnce(foo, 'getValue');
try {
yield foo.getValue();
throw new Error('should not run this');
} catch (err) {
err.message.should.equal('mm mock error');
}

const v = yield foo.getValue();
v.should.equal(1);

mm.errorOnce(foo, 'getValue');
try {
yield* foo.getValue();
throw new Error('should not run this');
} catch (err) {
err.message.should.equal('mm mock error');
}

const v1 = yield* foo.getValue();
v1.should.equal(1);
});
});
});

0 comments on commit c204c5e

Please sign in to comment.