I'm currently facing some difficulties mocking the 'os' module in NodeJS. I'd like to mock the 'networkInterfaces' function of the module to return a fixed configuration. It is however still returning the interface data of my machines.
I've created a small test case which isolates the problem:
something.ts
:
import * as os from 'os';
export class Something {
getInterfaces(){
return os.networkInterfaces()
}
}
something.spec.ts
:
import * as chai from 'chai';
import * as os from 'os';
import * as sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { Something } from './something';
import { ImportMock } from 'ts-mock-imports';
const expect = chai.expect;
chai.use(sinonChai);
const ip1 = '192.168.1.114';
const mockedInterfaces = {
en0: [
{
address: 'fe80::3e07:54ff:fe66:f0f8',
netmask: 'ffff:ffff:ffff:ffff::',
family: 'IPv6' as 'IPv6',
mac: '3c:07:54:66:f0:f8',
scopeid: 4,
internal: false,
cidr: '::1/128'
},
{
address: ip1,
netmask: '255.255.255.0',
family: 'IPv4' as 'IPv4',
mac: '3c:07:54:66:f0:f8',
internal: false,
cidr: '127.0.0.1/8'
}
]
};
describe('Something', () => {
let sandbox: sinon.SinonSandbox;
let something: Something;
let stub: sinon.SinonStub;
before(() => {
sandbox = sinon.createSandbox();
// sandbox.stub(os, 'networkInterfaces').callsFake(() => {
// return mockedInterfaces
// });
stub = ImportMock.mockFunction(os, 'networkInterfaces', mockedInterfaces);
something = new Something();
});
after(() => {
sandbox.restore();
stub.restore();
});
it('Returns the mock', () => {
const interfaces = something.getInterfaces();
expect(interfaces).to.deep.equal(mockedInterfaces);
});
});
Running it yields:
AssertionError: expected { Object (lo, eno2, ...) } to deeply equal { Object (en0) }
<Click to see difference>
at Context.<anonymous> (socket/xml2/something.spec.ts:57:36)
Which means that it is listing my interfaces as opposed to returning the mocked ones.
I'm kind of clueless on how to mock the nodejs module. Any guidance is appreciated.
Here is the unit test solution:
index.ts
:
import * as os from 'os';
export class Something {
getInterfaces() {
return os.networkInterfaces();
}
}
index.spec.ts
:
import proxyquire from 'proxyquire';
import sinon from 'sinon';
import { expect } from 'chai';
const ip1 = '192.168.1.114';
const mockedInterfaces = {
en0: [
{
address: 'fe80::3e07:54ff:fe66:f0f8',
netmask: 'ffff:ffff:ffff:ffff::',
family: 'IPv6' as 'IPv6',
mac: '3c:07:54:66:f0:f8',
scopeid: 4,
internal: false,
cidr: '::1/128'
},
{
address: ip1,
netmask: '255.255.255.0',
family: 'IPv4' as 'IPv4',
mac: '3c:07:54:66:f0:f8',
internal: false,
cidr: '127.0.0.1/8'
}
]
};
describe('Something', () => {
it('Returns the mock', () => {
const networkInterfacesStub = sinon.stub().returns(mockedInterfaces);
const { Something } = proxyquire('./', {
os: {
networkInterfaces: networkInterfacesStub
}
});
const something = new Something();
const interfaces = something.getInterfaces();
expect(interfaces).to.deep.equal(mockedInterfaces);
expect(networkInterfacesStub.calledOnce).to.be.true;
});
});
Unit test result with 100% coverage:
Something
✓ Returns the mock (190ms)
1 passing (198ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.spec.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/57690820