Javascript 笑话:模仿第三方模块

Javascript 笑话:模仿第三方模块,javascript,unit-testing,jestjs,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

最近,我一直在尝试通过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(`\\\\`);
  }
}
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?
  });
});
myModule.test.js

import os from 'os';
export const foo = () => {
  if (os.platform() === `win32`) {
    module = module.split(`\\`).join(`\\\\`);
  }
}
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?
  });
});

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

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

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

或者,仅使用一个文件:

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();
  });
});```

您可以将
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('os', () => { 
  const os = jest.requireActual('os');
  jest.spyOn(os, 'platform').mockReturnValue('mocked response');
  return os;
});

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

我的建议是学习如何使用摩卡和西农。已经创建了很多文档和示例。我将导入
os
,看看是否可以通过模拟(或存根)函数在
if
语句中使用的方法来影响它。尝试更改代码,使其使用聚合或依赖项注入。它将允许您以更简单的方式对其进行单元测试。在本例中,您可以模拟/stub
os
,然后将其传递给您的代码。努力让你的最后一个例子起作用。导入必须位于顶部否?require和import都需要吗?因此,如果我在该测试中运行foo(),那么myModule.js中的foo()将读取我在测试中设置的平台值?我将import移到顶部,但得到以下错误:
ReferenceError:mockOS未定义
,在
jest.mock
中,
jest.mock
调用被提升到顶部,但是我建议在import.Hi之前保留它。非常感谢。myModuleMock是否在任何地方定义?哦,你只是错过了我密码中的间谍。我现在就试试你的建议。谢谢布莱恩,这是一个有用的技巧。布莱恩,谢谢。在那里不需要使用间谍,对吗?我只是通过做:
jest.mock('os',()=>{return{platform:jest.fn()}})os.platform.mockReturnValue('customPlatformValue');myModuleMock()。是的,这也很好用。您甚至可以将其简化为
jest.mock('os',()=>({platform:jest.fn()}))…只需确保测试期间运行的其他代码不需要
os
,因为这将替换
os
中的所有代码@马格纳斯