开玩笑:如何在node_modules中模拟库?

时间:2019-04-04 20:38:46

标签: javascript reactjs jestjs

我正在尝试为使用node-forge的代码编写测试。由于某些原因,当我致电forge.md.sha256.create();时,测试会挂起:

  import forge from "node-forge";

  const privateKey = "foo";
  const storagePin = "bar";

  const md = forge.md.sha256.create();
  md.update(privateKey + storagePin);

  const metadataKey = md.digest().toHex();

作为一种解决方法,我正在尝试模拟该方法的实现,以使其仅返回一个硬编码的字符串:

import forge from "node-forge";
jest.mock("node-forge");

forge.mockImplementation(() => {
  return {
    md: {
      sha256: {
        create: () => {
          return {
            update: () => {},
            digest: () => {
              toHex: () => "foobar";
            }
          };
        }
      }
    }
  };
});


// tests

但是,我的测试仍然失败:

TypeError: _nodeForge2.default.mockImplementation is not a function

  at Object.<anonymous> (src/redux/epics/authentication-epic.test.js:20:27)
      at new Promise (<anonymous>)
  at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
  at processTicksAndRejections (internal/process/next_tick.js:81:5)

奇怪的是,当我尝试模拟自己的文件时,此策略非常有效。

模拟第三方库的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

您尝试过这样吗?有关此here的更多信息。

jest.mock('node-forge', () => ({
  md: {
    sha256: {
      create: () => ({
        update: () => {},
        digest: () => ({
          toHex: () => 'foobar'
        }),
      }),
    },
  },
}));

答案 1 :(得分:0)

default导出不是函数,因此Jest自动模拟操作不会用模拟函数代替默认导出...

...但是default导出对象。

来自Exploring ES6

  

...虽然您无法更改导入的值,但是可以更改它们所引用的对象。

因此,您只需将对象的md属性设置为您的模拟对象即可:

import forge from 'node-forge';
jest.mock('node-forge');

const toHex = jest.fn(() => 'foobar');
const digest = jest.fn(() => ({ toHex }));
const update = jest.fn();

forge.md = {  // <= set the md property to your mock
  sha256: {
    create: jest.fn(() => ({
      update,
      digest
    }))
  }
};

test('code uses the mock', () => {
  require('./path to your code');  // <= the mock will be used in the required code
  expect(forge.md.sha256.create).toHaveBeenCalled();  // Success!
  expect(update).toHaveBeenCalledWith('foobar');  // Success!
  expect(digest).toHaveBeenCalled();  // Success!
  expect(toHex).toHaveBeenCalled();  // Success
});