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?
});
});
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();
});
});```
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With