最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Jest: Mocking third-party modules - Stack Overflow

programmeradmin0浏览0评论

I have been trying to learn unit testing with Jest recently, reading through the docs and various articles.

One thing I have not been able to figure out is the following:

I am trying to test a nodeJS module that has an if statement conditional on os.platform().

Is there any way for my test to set/mock the os.platform return value to something else, so when the Jest runs the test file the test file will read the os.platform() value specified in the test suite?

PS: foo() cannot accept the platform via dependency injection. The implementation of foo() is fixed.

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

I have been trying to learn unit testing with Jest recently, reading through the docs and various articles.

One thing I have not been able to figure out is the following:

I am trying to test a nodeJS module that has an if statement conditional on os.platform().

Is there any way for my test to set/mock the os.platform return value to something else, so when the Jest runs the test file the test file will read the os.platform() value specified in the test suite?

PS: foo() cannot accept the platform via dependency injection. The implementation of foo() is fixed.

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?
  });
});
Share Improve this question edited May 3, 2019 at 23:57 Magnus asked May 3, 2019 at 13:22 MagnusMagnus 7,82114 gold badges65 silver badges101 bronze badges 4
  • My advice is learn how to do it with Mocha and Sinon instead. There is a lot of documentation and examples already created. – acarlstein Commented May 3, 2019 at 13:27
  • I would import os and see if I can affect it by mocking (or stubbing) the method your function is using in the if statement – acarlstein Commented May 3, 2019 at 13:27
  • Try change your code so it uses aggregation or dependency injection. It will allow you for an easier way to unit test it. In this case, you could mock/stub os and then pass it to your code. – acarlstein Commented May 3, 2019 at 13:33
  • I've added an example using your own test code – enapupe Commented May 3, 2019 at 19:44
Add a comment  | 

2 Answers 2

Reset to default 9

You can import os into your test file and use jest.spyOn to mock it like this:

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

I prefer this approach because it keeps the mock closer to the test that it is affecting.


If you want to use jest.mock with a factory function then you can do it like this:

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

Note that the factory function must be completely self-contained.

You can mock the os module by adding a os.js file on the __mocks__ dir:

// ./__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') // ✔️
})

or, with just a single file:

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')
})

so your test file should look something like:

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();
  });
});```
发布评论

评论列表(0)

  1. 暂无评论