用Jest模拟继承的类

时间:2018-02-20 15:19:02

标签: node.js unit-testing sockets mocking jest

我正在延长net.Socket。在这样做时,我将覆盖connect方法,如下所示。

class ENIP extends Socket {
    constructor() {
        super();

        this.state = {
            session: { id: null, establishing: false, established: false },
            error: { code: null, msg: null }
        };
    }

    connect(IP_ADDR) {
        const { registerSession } = encapsulation; //returns a buffer to send

        this.state.session.establishing = true;

        return new Promise(resolve => {
            super.connect(EIP_PORT, IP_ADDR, () => { // This is what i want to mock -> super.connect
                this.state.session.establishing = false;

                this.write(registerSession());
                resolve();
            });
        });
    }
}

我想模拟底层的 Socket 类,以便我可以模拟super.connect。在查看了Facebook的docs之后,我不确定如何继续为这个类开发测试,因为所有方法都会扩展super.someMethodToMock。有谁知道我应采取的方法?如果有任何澄清我可以提供的详细信息,请告诉我。

1 个答案:

答案 0 :(得分:0)

您可以使用jest.spyOn(object, methodName)Socket.prototype上创建模拟方法。

例如

index.js

import { Socket } from 'net';

const EIP_PORT = 3000;
const encapsulation = {
  registerSession() {
    return 'session';
  },
};

export class ENIP extends Socket {
  constructor() {
    super();
    this.state = {
      session: { id: null, establishing: false, established: false },
      error: { code: null, msg: null },
    };
  }

  connect(IP_ADDR) {
    const { registerSession } = encapsulation;
    this.state.session.establishing = true;

    return new Promise((resolve) => {
      super.connect(EIP_PORT, IP_ADDR, () => {
        this.state.session.establishing = false;
        this.write(registerSession());
        resolve();
      });
    });
  }
}

index.test.js

import { ENIP } from './';
import { Socket } from 'net';

describe('ENIP', () => {
  afterAll(() => {
    jest.restoreAllMocks();
  });
  describe('#connect', () => {
    it('should pass', async () => {
      const writeSpy = jest.spyOn(Socket.prototype, 'write').mockImplementation();
      const connectSpy = jest.spyOn(Socket.prototype, 'connect').mockImplementationOnce((port, addr, callback) => {
        callback();
      });
      const enip = new ENIP();
      await enip.connect('localhost');
      expect(writeSpy).toBeCalledWith('session');
      expect(connectSpy).toBeCalledWith(3000, 'localhost', expect.any(Function));
    });
  });
});

具有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/48888509/index.test.jsx (10.43s)
  ENIP
    #connect
      ✓ should pass (7ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.jsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.357s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/48888509