Модульное тестирование функции nodejs с использованием `fs`, заключенной в` promisify` - PullRequest
0 голосов
/ 24 апреля 2020

В следующем коде у меня есть функция, которая ищет файл в файловой системе на основе предоставленной конфигурации.

const fs = require('fs');
const { promisify } = require('util');

const lstat = promisify(fs.lstat);

async function doSomething(someFilePath) {
    try {
       const stats = await lstat(someFilePath);
    } catch (err) {
       throw err;
    }

    // do something with the file stats
}

module.exports = doSomething;

Отсюда я пытаюсь протестировать функцию doSomething, но это терпит неудачу, потому что пути файла, которые я предоставляю, фактически не существуют. Приведенный ниже код работал , когда я использовал lstatSync без promisify.

const fs = require('fs');
const sinon = require('sinon');

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

describe('The test', function() {

    let lstatStub;

    beforeEach(function() {
        lstatStub = sinon.stub(fs, 'lstatSync');
    });

    afterEach(function() { sinon.restore() });

    it('should pass', async function() {
        lstatStub.withArgs('image.jpg').returns({
            isFile: () => true,
            isDirectory: () => false,
        });

        assert(await doSomething('image.jpg')).ok();
    });

})

. Теперь происходит сбой, поскольку Error: ENOENT: no such file or directory, lstat 'image.jpg'. Я попытался обернуть заглушку в promisify или экспортировать promisify ed функции в тест в заглушку. Оба не сработали.

Как заглушить метод promisify ed fs?

1 Ответ

0 голосов
/ 25 апреля 2020

Вы можете использовать Link Seams и proxyquire пакет для функции заглушки promisify.

Например,

main.js:

const fs = require('fs');
const { promisify } = require('util');

const lstat = promisify(fs.lstat);

async function doSomething(someFilePath) {
  return await lstat(someFilePath);
}

module.exports = doSomething;

main.test.js:

const sinon = require('sinon');
const proxyquire = require('proxyquire');
const { expect } = require('chai');

describe('61412987', () => {
  it('should pass', async () => {
    const lstatStub = sinon.stub().resolves('fake data');
    const utilStub = { promisify: sinon.stub().callsFake(() => lstatStub) };
    const doSomethng = proxyquire('./main', {
      util: utilStub,
    });

    const actual = await doSomethng('/root/avatar.jpg');
    expect(actual).to.be.equal('fake data');
    sinon.assert.calledOnce(utilStub.promisify);
    sinon.assert.calledWithExactly(lstatStub, '/root/avatar.jpg');
  });
});

Результаты модульного теста со 100% покрытием:

  61412987
    ✓ should pass (1894ms)


  1 passing (2s)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 main.js  |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------

Исходный код: https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/61412987

...