开玩笑:模拟第三方模块

时间:2019-05-03 13:22:05

标签: javascript unit-testing jestjs

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

我无法弄清的一件事是:

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

我的测试是否可以将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(`\\\\`);
  }
}

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?
  });
});

2 个答案:

答案 0 :(得分:1)

您可以通过在os目录上添加os.js文件来模拟__mocks__模块:

// ./__mocks__/os.js
const os = jest.requireActual('os')

os.platform = jest.fn().mockReturnValue('testPlatform')
module.exports = os

// ./tests/whatever/some.test.js
import os from 'os'

jest.mock('os')

test('os', () => {
  expect(os.platform()).toBe('testPlatform') // ✔️
})

或者,只有一个文件:

const mockOS = jest.requireActual('os')
mockOS.platform = jest.fn().mockReturnValue('testPlatform')
jest.mock('os', () => mockOS)

import os from 'os'

test('os', () => {
  expect(os.platform()).toBe('testPlatform')
})

因此您的测试文件应类似于:

const mockOS = jest.requireActual('os')
mockOS.platform = jest.fn().mockReturnValue('testPlatform')
jest.mock('os', () => mockOS)


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

describe('myModule', () => {
  it('can run with different os.platform() values', () => {
    myModuleMock();
    expect(myModuleMock).toHaveBeenCalled();
  });
});```

答案 1 :(得分:1)

您可以将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!
  });
});

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


如果要将jest.mock与工厂功能一起使用,则可以这样操作:

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

请注意,工厂功能必须完全独立。