首页 > 解决方案 > 如何使用 Sinon.JS 存根承诺的方法?

问题描述

给定以下代码:(请注意,访问已被承诺)

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中承诺了给定custom.js

参考:

标签: javascriptnode.jsmocha.jssinonchai

解决方案


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

您正在寻找的是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');
    });
});

自定义.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.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);
    });
});

推荐阅读