开玩笑:在手动模拟中恢复原始模块的实现

时间:2019-01-11 09:48:53

标签: javascript unit-testing jestjs

我有一个非常普通的测试用例,我不确定那里最好的方法是什么。

上下文

我想测试依赖于用户区依赖性的模块。用户名依赖项(neat-csv导出单个函数,该函数返回Promise

目标

我想模拟neat-csv的行为,以便它拒绝一次测试的错误。然后,我想还原原始的模块实现。

AFAIK,我无法在此处使用jest.spyOn,因为该模块会导出单个函数。

因此,我认为使用手动模拟是合适的并且可以工作。但是我无法弄清楚如何通过手动模拟还原原始实现。

简化示例

为简单起见,这是我要测试的模块的简化版本:

'use strict';

const neatCsv = require('neat-csv');

async function convertCsvToJson(apiResponse) {
  try {
    const result = await neatCsv(apiResponse.body, {
      separator: ';'
    });
    return result;
  } catch (parseError) {
    throw parseError;
  }
}

module.exports = {
  convertCsvToJson
};

这是测试的第二次测试(非模拟版本)失败的尝试:

'use strict';

let neatCsv = require('neat-csv');
let { convertCsvToJson } = require('./module-under-test.js');

jest.mock('neat-csv', () =>
  jest.fn().mockRejectedValueOnce(new Error('Error while parsing'))
);

const csv = 'type;part\nunicorn;horn\nrainbow;pink';
const apiResponse = {
  body: csv
};

const rejectionOf = (promise) =>
  promise.then(
    (value) => {
      throw value;
    },
    (reason) => reason
  );

test('mocked version', async () => {
  const e = await rejectionOf(convertCsvToJson(apiResponse));
  expect(neatCsv).toHaveBeenCalledTimes(1);
  expect(e.message).toEqual('Error while parsing');
});

test('non mocked version', async () => {
  jest.resetModules();
  neatCsv = require('neat-csv');
  ({ convertCsvToJson } = require('./module-under-test.js'));

  const result = await convertCsvToJson(apiResponse);
  expect(JSON.stringify(result)).toEqual(
    '[{"type":"unicorn","part":"horn"},{"type":"rainbow","part":"pink"}]'
  );
});

我想知道开玩笑是设计用来做这种事情还是我走错了路,应该注入整洁的csv吗?

处理此问题的惯用方式是什么?

1 个答案:

答案 0 :(得分:0)

是的,Jest 被设计用来做这种事情。

您要查找的API方法是jest.doMock。它提供了一种模拟模块的方式,而不会发生 jest.mock 所引起的隐式提升,从而使您可以在测试范围内进行模拟。

以下是您的测试代码的有效示例,它显示了这一点:

const csv = 'type;part\nunicorn;horn\nrainbow;pink';
const apiResponse = {
    body: csv
};

const rejectionOf = promise =>
    promise.then(value => {
        throw value;
    }, reason => reason);

test('mocked version', async () => {
    jest.doMock('neat-csv', () => jest.fn().mockRejectedValueOnce(new Error('Error while parsing')));
    const neatCsv = require('neat-csv');
    const { convertCsvToJson } = require('./module-under-test.js');
    const e = await rejectionOf(convertCsvToJson(apiResponse));
    expect(neatCsv).toHaveBeenCalledTimes(1);
    expect(e.message).toEqual('Error while parsing');
    jest.restoreAllMocks();
});

test('non mocked version', async () => {
    const { convertCsvToJson } = require('./module-under-test.js');

    const result = await convertCsvToJson(apiResponse);
    expect(JSON.stringify(result)).toEqual('[{"type":"unicorn","part":"horn"},{"type":"rainbow","part":"pink"}]');
});