วิธีทดสอบ/จำลองไคลเอนต์ socket.io

ฉันกำลังพยายามเยาะเย้ยวิธีการเปล่งแสงจาก io แต่ฉันไม่รู้ว่าจะเยาะเย้ยมันอย่างไร นี่คือไฟล์ 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 | 

โปรดอย่าหยาบคายกับคำตอบของคุณ ฉันยังใหม่กับการทดสอบและฉันหลงทางจริงๆ ขอบคุณล่วงหน้าสำหรับคำตอบของคุณ!!


person Paola Arredondo    schedule 26.08.2020    source แหล่งที่มา
comment
วิธีการของคุณค่อนข้างแม่นยำ คุณเพียงแค่ต้องย้ายบล็อก jest.mock ในขอบเขตที่คุณนำเข้าไลบรารี เช่น ก่อนบล็อกอธิบาย   -  person Teneff    schedule 27.08.2020


คำตอบ (1)


รหัสทดสอบของคุณมีปัญหาสามประการ:

  1. ย้ายบล็อคโค้ด jest.mock ไปยังขอบเขตโมดูล มันจะถูกยกไปที่ด้านบนของบล็อคโค้ด ซึ่งหมายความว่าแม้ว่าคุณจะ import Join from './Join' โมดูลเป็นอันดับแรก (ในระดับลำดับการเขียนโค้ด) โมดูล socket.io-client จะเป็นเวอร์ชันที่จำลอง ทั้งสำหรับไฟล์ทดสอบและไฟล์ที่ผ่านการทดสอบน้อย

  2. ใช้การอ้างอิงเดียวกันของวัตถุซ็อกเก็ตที่จำลองในโรงงานจำลอง มิฉะนั้นวัตถุซ็อกเก็ตในโค้ดทดสอบและวัตถุซ็อกเก็ตในโค้ดที่ทดสอบจะไม่เป็นการอ้างอิงเดียวกันสำหรับการเรียกใช้ฟังก์ชัน io ทุกครั้ง

  3. ฟังก์ชันที่ไม่ระบุชื่อไม่ใช่การอ้างอิงเดียวกันกับฟังก์ชันในโค้ดทดสอบ ดังนั้นการยืนยัน .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));
  });
});

ผลการทดสอบหน่วยพร้อมรายงานความครอบคลุม:

 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

ซอร์สโค้ด: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/63605899

person slideshowp2    schedule 07.09.2020