Jest:嘲笑第三方模块

Mag*_*nus 7 javascript unit-testing jestjs

我最近一直在尝试使用 Jest 学习单元测试,阅读文档和各种文章。

我无法弄清楚的一件事如下:

我正在尝试测试一个 nodeJS 模块,该模块具有if以 为条件的语句os.platform()

有什么方法可以让我的测试将os.platform返回值设置/模拟为其他值,以便当 Jest 运行测试文件时,测试文件将读取测试套件中指定的 os.platform() 值?

PS:foo()无法通过依赖注入接受平台。的实施foo()是固定的。

myModule.js

import os from 'os';
export const foo = () => {
  if (os.platform() === `win32`) {
    module = module.split(`\\`).join(`\\\\`);
  }
}
Run Code Online (Sandbox Code Playgroud)

myModule.test.js

import * as myModule from '../myModule.js';

// Guessing I need to use spyOn, to test the actual module code?
const myModuleMock = jest.spyOn(myModule, 'foo');

describe('myModule', () => {
  it('can run with different os.platform() values', () => {
    myModuleMock();
    expect(myModuleMock).toHaveBeenCalled();
    // How do I specify what value os.platform() in foo() should return?
  });
});
Run Code Online (Sandbox Code Playgroud)

Bri*_*ams 7

您可以导入os到测试文件中并使用jest.spyOn它来模拟它,如下所示:

import * as myModule from '../myModule.js';
import os from 'os';

describe('myModule', () => {
  it('can run with different os.platform() values', () => {
    const spy = jest.spyOn(os, 'platform');
    spy.mockReturnValue('mocked response');  // <= mock the return value

    myModule.foo();

    expect(spy).toHaveBeenCalled();  // Success!
  });
});
Run Code Online (Sandbox Code Playgroud)

我更喜欢这种方法,因为它使模拟更接近它所影响的测试。


如果你想与工厂函数一起使用,jest.mock那么你可以这样做:

jest.mock('os', () => { 
  const os = jest.requireActual('os');
  jest.spyOn(os, 'platform').mockReturnValue('mocked response');
  return os;
});
Run Code Online (Sandbox Code Playgroud)

请注意,工厂函数必须是完全独立的。


ena*_*upe 5

您可以通过在目录中os添加文件来模拟模块:os.js__mocks__

\n\n
// ./__mocks__/os.js\nconst os = jest.requireActual('os')\n\nos.platform = jest.fn().mockReturnValue('testPlatform')\nmodule.exports = os\n\n
Run Code Online (Sandbox Code Playgroud)\n\n
// ./tests/whatever/some.test.js\nimport os from 'os'\n\njest.mock('os')\n\ntest('os', () => {\n  expect(os.platform()).toBe('testPlatform') // \xe2\x9c\x94\xef\xb8\x8f\n})\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,只有一个文件:

\n\n
const mockOS = jest.requireActual('os')\nmockOS.platform = jest.fn().mockReturnValue('testPlatform')\njest.mock('os', () => mockOS)\n\nimport os from 'os'\n\ntest('os', () => {\n  expect(os.platform()).toBe('testPlatform')\n})\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以你的测试文件应该类似于:

\n\n
const mockOS = jest.requireActual('os')\nmockOS.platform = jest.fn().mockReturnValue('testPlatform')\njest.mock('os', () => mockOS)\n\n\nimport * as myModule from '../myModule.js';\n\ndescribe('myModule', () => {\n  it('can run with different os.platform() values', () => {\n    myModuleMock();\n    expect(myModuleMock).toHaveBeenCalled();\n  });\n});```\n
Run Code Online (Sandbox Code Playgroud)\n