如何使用Sinon.JS存根一个promisified方法?

时间:2018-05-18 11:38:56

标签: javascript node.js mocha sinon chai

给出以下代码: (请注意,访问已被宣传)

const fs = require('fs')
const util = require('util')
const access = util.promisify(fs.access)

const custom = () => {
  return access('myfile', fs.constants.R_OK)
    .then(() => {
      return true
    }).catch(err => {
      if (err.code !== 'ENOENT') throw err
      return false
    }).then(fileExists => {
      return `File exists: ${fileExists}`
    })
}

module.exports = custom

我的单元测试无效,因为正在调用真正的access方法而不是存根方法:

const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
const custom = require('./custom')
const fs = require('fs')
const sinon = require('sinon')

chai.use(chaiAsPromised)
const expect = chai.expect

describe('custom', () => {
  let sandbox = sinon.createSandbox()

  afterEach(function () {
    sandbox.restore()
  })

  it('should return file exists true', () => {
    sandbox.stub(fs, 'access').yields(null)
    return expect(custom()).to.eventually.equal('File exists: true')
  })

  it('should return file exists false', () => {
    const error = new Error('No such file or directory')
    error.code = 'ENOENT'
    sandbox.stub(fs, 'access').yields(error)
    return expect(custom()).to.eventually.equal('File exists: false')
  })
})

如何使测试有效,在access文件中宣传了{m {1}}

参考文献:

1 个答案:

答案 0 :(得分:0)

更新 问题已更新。回答底部的原始问题

您要找的是Proxyquire。 问题是custom.js需要自己的fs,并且您正在测试文件中的fsProxyquire将需要一个文件,并替换该文件所需的任何文件/函数。

在你的例子中,它会像这样。 (使用mocha <test file path>

运行它

测试文件:

const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const proxyquire = require('proxyquire');

chai.use(chaiAsPromised);
const expect = chai.expect;

describe('custom', () => {
    let custom;

    const stubs = {
        fs: {
            accessAsync: () => {
                // Since you mentioned that fs was promisified, we will
                // make this a promise as well.
                return Promise.resolve();
            }
        },
        bluebird: {
            // Stop bluebird from promisifying, since we handle it above.
            promisifyAll: (req => req),
        }
    };

    before(async function () {
        custom = proxyquire('./custom', stubs);
    });

    it('should return file exists true', () => {
        return expect(custom()).to.eventually.equal('File exists: true');
    });
});

<强> custom.js

'use strict';

const bluebird = require('bluebird');
const fs = bluebird.promisifyAll(require('fs'));

module.exports = async function() {
    let exists = true;
    await fs.accessAsync('nonimportant.path', fs.constants.F_OK)
        .catch( () => { exists = false; });
    return `File exists: ${exists}`;
};

原始回答

在这种情况下不需要使用蓝鸟,Sinon可以处理它。

您需要使用sinon.stub()功能。可以这样做:

const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinon = require('sinon');
const fs = require('fs');

chai.use(chaiAsPromised);
const expect = chai.expect;

describe('fs.stat', function(){
    before(function() {
        sinon.stub(fs, 'stat').resolves('Your desired value');
    });

    it('should should be called', function(done){
        expect(fs.stat('./some.file'))
            .to.eventually.equal('Your desired value')
            .notify(done);
    });
});