模拟 'os' nodejs 模块问题

Mocking 'os' nodejs module issues

我目前在模拟 NodeJS 中的 'os' 模块时遇到了一些困难。 我想将模块的 'networkInterfaces' 功能模拟为 return 固定配置。然而,它仍在 return 处理我机器的接口数据。

我创建了一个小测试用例来隔离问题: 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);
  });
});

运行 它产生:


AssertionError: expected { Object (lo, eno2, ...) } to deeply equal { Object (en0) }
<Click to see difference>

    at Context.<anonymous> (socket/xml2/something.spec.ts:57:36)

这意味着它列出了我的接口,而不是 return模拟的接口。

我对如何模拟 nodejs 模块一无所知。任何指导表示赞赏。

单元测试解决方案如下:

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

100% 覆盖率的单元测试结果:

  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 |                   |
---------------|----------|----------|----------|----------|-------------------|

源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/Whosebug/57690820