如何测试/模拟socket.io客户端

时间:2020-08-26 21:20:46

标签: reactjs unit-testing socket.io mocking jestjs

我正在尝试模拟io的emit方法,但我不知道如何模拟它。这是我的Join.jsx文件

//Join.jsx

import React from 'react';
import io from 'socket.io-client';

const Join = () => {
  let socket;
  const ENDPOINT = 'localhost:5000';

  const join = () => {
    socket = io(ENDPOINT);
    socket.emit('join', { name: 'Paola', room: '1' }, () => { });
  };

  return (
    <div className="join-container">
        <a className="join-button" onClick={join}>Sign in</a>
    </div>
  );
};

export default Join;

这是我尝试过的一件事

//Join.test.jsx
import React from 'react';
import { shallow } from 'enzyme';
import io from 'socket.io-client';
import Join from './Join';

describe(('Join') => {
  it(('joins a chat') => {
    jest.mock('socket.io-client', () => {
      return jest.fn(() => ({
        emit: jest.fn(),
      }));
    });
    const ENDPOINT = 'localhost:5000';
    const mockSocket = io(ENDPOINT);
    const joinWrapper = shallow(<Join />);
    joinWrapper.find('a').simulate('click');
    expect(mockSocket.emit).toHaveBeenCalledWith('join', { name: 'Paola', room: '1' }, () => { });
  })
})

这是我在终端中遇到的错误

expect(received).toHaveBeenCalledWith(...expected)

    Matcher error: received value must be a mock or spy function

    Received has type:  function
    Received has value: [Function anonymous]

      52 |     const joinWrapper = shallow(<Join />);
      53 |     joinWrapper.find('a').simulate('click');
    > 54 |     expect(mockSocket.emit).toHaveBeenCalledWith('join', { name: 'Paola', room: '1' }, () => { });
         |                             ^
      55 |   });
      56 | });
      57 | 

请不要对您的回答无礼,我是测试新手,我真的迷失了。预先感谢您的答复!

1 个答案:

答案 0 :(得分:0)

您的测试代码存在三个问题:

  1. jest.mock代码块移至模块作用域。它将被提升到代码块的顶部。这意味着即使您首先import Join from './Join'模块(按代码编写顺序),socket.io-client模块仍是模拟版本,适用于测试文件和被测文件。

  2. 在模拟工厂中使用模拟的套接字对象的相同引用,否则对于每次{{1}的调用,测试代码中的套接字对象和测试代码中的套接字对象将不是相同的引用}功能。

  3. 匿名函数与测试代码中的引用不同。因此io断言将失败。相反,您应该使用.toBeCalledWith()

这是单元测试解决方案:

expect.any(Function)

Join.tsx

import React from 'react'; import io from 'socket.io-client'; const Join = () => { let socket; const ENDPOINT = 'localhost:5000'; const join = () => { socket = io(ENDPOINT); socket.emit('join', { name: 'Paola', room: '1' }, () => {}); }; return ( <div className="join-container"> <a className="join-button" onClick={join}> Sign in </a> </div> ); }; export default Join;

Join.test.tsx

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

import React from 'react';
import { shallow } from 'enzyme';
import io from 'socket.io-client';
import Join from './Join';

jest.mock('socket.io-client', () => {
  const mSocket = {
    emit: jest.fn(),
  };
  return jest.fn(() => mSocket);
});

describe('Join', () => {
  it('joins a chat', () => {
    const ENDPOINT = 'localhost:5000';
    const mockSocket = io(ENDPOINT);
    const joinWrapper = shallow(<Join />);
    joinWrapper.find('a').simulate('click');
    expect(mockSocket.emit).toHaveBeenCalledWith('join', { name: 'Paola', room: '1' }, expect.any(Function));
  });
});

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