Как заглушить обещанный метод с помощью Sinon.JS? - PullRequest
0 голосов
/ 18 мая 2018

Учитывая следующий код: (Обратите внимание, что доступ был обещан)

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')
  })
})

Как сделать тест работоспособным, Givem access обещан в файле custom.js?

Ссылки:

1 Ответ

0 голосов
/ 18 мая 2018

Обновление Вопрос был обновлен.Ответ на оригинальный вопрос внизу

Что вы ищете, это Proxyquire .Проблема в том, что для custom.js требуется собственный fs, а вы вставляете в файл теста fs.Proxyquire потребует файл и заменит любые файлы / функции, которые вам нужны, для этого файла.

В вашем примере это будет примерно так.(запустите его с 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}`;
};

Оригинальный ответ

В этом случае нет необходимости использовать bluebird, Синон может с этим справиться.

Вам необходимо использовать 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);
    });
});
...