首页 > 解决方案 > 笑话:模拟第三方模块

问题描述

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

我无法弄清楚的一件事是:

我正在尝试测试具有if条件语句的 nodeJS 模块os.platform()

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

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

我的模块.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?
  });
});

标签: javascriptunit-testingjestjs

解决方案


您可以导入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;
});

请注意,工厂函数必须是完全自包含的。


推荐阅读