Typescript, React & Socket.io-client Tests



我正试图弄清楚如何编写一个Typescript/Rect应用程序,该应用程序使用socket.io与服务器通信,从而与其他客户端通信。然而,我想写一些这样做的测试

在我的示例应用程序中,我有:

import io, { Socket } from 'socket.io-client';

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

const join = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
event.preventDefault();
socket = io(ENDPOINT);
socket.emit('join', { name: 'Paola', room: '1' }, () => {});
};

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

export default App;

我的测试看起来像:

import App from './App';
import { render, screen, fireEvent } from '@testing-library/react';
import 'setimmediate';


describe('Join', () => {
let mockEmitter = jest.fn();
beforeEach(() => {
jest.mock('socket.io-client', () => {
const mockedSocket = {
emit: mockEmitter,
on: jest.fn((event: string, callback: Function) => {}),
};
return jest.fn(() => {
return mockedSocket;
}
);
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('joins a chat',  () => {
// Arrange
render(<App />);

const btn =  screen.getByTestId('join-button');

// Act
fireEvent.click(btn);

// Assert
expect(btn).toBeInTheDocument();
expect(mockEmitter).toHaveBeenCalled();
});
});

我只想确保我可以模拟socket.io-client,这样我就可以验证消息是否发送到客户端,以及它(稍后(是否对发送的消息做出反应。

然而,测试失败了,它似乎没有使用我的mock。

Error: expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls:    0

在手册mocks#examples文档中,有一个注释:

注意:为了正确地mock,Jest需要jest.mock('moduleName')require/import语句处于相同的范围内。

因此,有两种解决方案:

app.tsx:

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

选项1:调用jest.mock,导入测试文件模块范围内的./app模块

app.test.tsx:

import App from './App';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
let mockEmitter = jest.fn();
jest.mock('socket.io-client', () => {
return jest.fn(() => ({
emit: mockEmitter,
on: jest.fn(),
}));
});
describe('Join', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('joins a chat', () => {
// Arrange
render(<App />);
const btn = screen.getByTestId('join-button');
// Act
fireEvent.click(btn);
// Assert
expect(btn).toBeInTheDocument();
expect(mockEmitter).toHaveBeenCalled();
});
});

选项2:由于您在beforeEach钩子中调用jest.mock,因此require为'/在beforeEach钩子函数作用域中的app'模块

app.test.tsx:

import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
describe('Join', () => {
let mockEmitter = jest.fn();
let App;
beforeEach(() => {
App = require('./app').default;
jest.mock('socket.io-client', () => {
const mockedSocket = {
emit: mockEmitter,
on: jest.fn(),
};
return jest.fn(() => mockedSocket);
});
});
afterEach(() => {
jest.clearAllMocks();
});
it('joins a chat', () => {
// Arrange
render(<App />);
const btn = screen.getByTestId('join-button');
// Act
fireEvent.click(btn);
// Assert
expect(btn).toBeInTheDocument();
expect(fakeEmitter).toHaveBeenCalled();
});
});

软件包版本:

"jest": "^26.6.3",
"ts-jest": "^26.4.4"

jest.config.js:

module.exports = {
preset: 'ts-jest/presets/js-with-ts',
testEnvironment: 'jsdom'
}

相关内容

  • 没有找到相关文章

最新更新