如何测试/模拟 socket.io 客户端 [英] How to test/mock socket.io client

查看:180
本文介绍了如何测试/模拟 socket.io 客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

//Join.jsx从反应"导入反应;从'socket.io-client'导入io;const Join = () =>{让插座;const 端点 = '本地主机:5000';const join = () =>{套接字= io(端点);socket.emit('join', { name: 'Paola', room: '1' }, () => { });};返回 (<div className="join-container"><a className="join-button";onClick={join}>登录</a>

);};导出默认加入;

这是我尝试过的一件事

//Join.test.jsx从反应"导入反应;从酶"导入{浅};从'socket.io-client'导入io;从'./Join'导入加入;描述(('加入')=> {it(('加入聊天') => {jest.mock('socket.io-client', () => {返回 jest.fn(() => ({发出: jest.fn(),}));});const 端点 = '本地主机:5000';const mockSocket = io(ENDPOINT);const joinWrapper = 浅(<Join/>);joinWrapper.find('a').simulate('click');expect(mockSocket.emit).toHaveBeenCalledWith('join', { name: 'Paola', room: '1' }, () => { });})})

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

expect(received).toHaveBeenCalledWith(...expected)匹配器错误:接收的值必须是模拟或间谍函数接收有类型:函数Received has value: [函数匿名]52 |const joinWrapper = 浅(<Join/>);53 |joinWrapper.find('a').simulate('click');>54 |expect(mockSocket.emit).toHaveBeenCalledWith('join', { name: 'Paola', room: '1' }, () => { });|^55 |});56 |});57 |

请不要对您的回答无礼,我是测试新手,我真的很迷茫.提前感谢您的回复!!

解决方案

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

  1. jest.mock 代码块移动到模块范围.它将被提升到代码块的顶部.这意味着即使您先import Join from './Join' 模块(在代码编写顺序级别),socket.io-client 模块也会被模拟版本,用于测试文件和被测文件.

  2. 在mock factory中使用与mocked socket对象相同的引用,否则每次调用io时,测试代码中的socket对象和测试代码中的socket对象将不会是同一个引用 函数.

  3. 匿名函数与测试代码中的引用不同.所以 .toBeCalledWith() 断言将失败.相反,您应该使用 expect.any(Function).

这是单元测试解决方案:

Join.tsx:

从'react'导入React;从'socket.io-client'导入io;const Join = () =>{让插座;const 端点 = '本地主机:5000';const join = () =>{套接字= io(端点);socket.emit('join', { name: 'Paola', room: '1' }, () => {});};返回 (<div className="join-container"><a className="join-button";onClick={join}>登入</a>

);};导出默认加入;

Join.test.tsx:

从'react'导入React;从酶"导入{浅};从'socket.io-client'导入io;从'./Join'导入加入;jest.mock('socket.io-client', () => {const mSocket = {发出: jest.fn(),};return jest.fn(() => mSocket);});描述('加入',()=> {it('加入聊天', () => {const 端点 = '本地主机:5000';const mockSocket = io(ENDPOINT);const joinWrapper = 浅(<Join/>);joinWrapper.find('a').simulate('click');expect(mockSocket.emit).toHaveBeenCalledWith('join', { name: 'Paola', room: '1' }, expect.any(Function));});});

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

 通过 src/stackoverflow/63605899/Join.test.tsx加入✓ 加入聊天(14 毫秒)----------|----------|---------|---------|----------|--------------------|档案 |% stmts |% 分支 |% 函数 |% 行 |未覆盖的行#s |----------|----------|---------|---------|----------|--------------------|所有文件 |100 |100 |66.67 |100 ||加入.tsx |100 |100 |66.67 |100 ||----------|----------|---------|---------|----------|--------------------|测试套件:1 次通过,总共 1 次测试:1 次通过,共 1 次快照:共 0 个时间:5.162s,估计13s

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

I am trying to mock the emit method from io but I don't know how to mock it. This is my Join.jsx file

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

This is one thing I have tried

//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' }, () => { });
  })
})

This is the error that I get in the terminal

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 | 

Please don't be rude with your answers, I'm new at testing and I am really lost. Thank you in advance for your responses!!

解决方案

There are three problems with your test code:

  1. Move the jest.mock code block to module scope. It will be hoisted to the top of the code block. Which means even if you import Join from './Join' module first(At the level of code writing order), the socket.io-client module will be the mocked version, both for the test file and the file under-tested.

  2. Use the same reference of the mocked socket object in the mock factory, otherwise the socket object in the test code and the socket object in the tested code will not be the same reference for every call of io function.

  3. The anonymous functions is not the same reference as the one in the test code. So the .toBeCalledWith() assertion will be failed. Instead, you should use expect.any(Function).

Here is the unit test solution:

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

unit test result with coverage report:

 PASS  src/stackoverflow/63605899/Join.test.tsx
  Join
    ✓ joins a chat (14ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |    66.67 |      100 |                   |
 Join.tsx |      100 |      100 |    66.67 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.162s, estimated 13s

source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/63605899

这篇关于如何测试/模拟 socket.io 客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆