我想测试messageListener是否将数据附加到消息数组状态。但是,我对此有一些障碍。1. 无法在无状态组件内部测试方法 2. React 钩子不能在组件函数外部使用。
我不知道如何解决这个问题?我应该使用不同的方法来测试吗?我应该将其提取到自定义钩子中吗?我是 Enzyme 和 React 钩子的新手。我基本上想测试如果 socket.io 接收到 MESSAGE 事件,该组件会将另一个项目附加到要在 MessageFeed 中显示的消息数组中。
完整的项目也可以在https://github.com/Hyllesen/react-chat上看到
应用程序.js
import React from "react";
import UsernameInput from "components/UsernameInput";
import MessageFeed from "components/MessageFeed";
import io from "socket.io-client";
import * as eventTypes from "eventTypes";
function joinWithUsername(username) {
const socket = io("http://localhost:3001");
socket.emit(eventTypes.USER_JOIN, { username });
socket.on(eventTypes.MESSAGE, messageListener);
}
function messageListener(data, setMessages) {
setMessages([...messages, data]);
}
const App = () => {
const [messages, setMessages] = React.useState([]);
return (
<div className="App">
<UsernameInput onSubmit={joinWithUsername} />
<MessageFeed messages={messages} />
</div>
);
};
export default App;
export { joinWithUsername, messageListener };
应用程序.test.js
import React from "react";
import App, { joinWithUsername, messageListener } from "../App";
import { shallow } from "enzyme";
import io from "socket.io-client";
import * as eventTypes from "eventTypes";
let wrapper, setState, useStateSpy;
jest.mock("socket.io-client", () => {
const emit = jest.fn();
const on = jest.fn();
const socket = { emit, on };
return jest.fn(() => socket);
});
describe("App", () => {
beforeEach(() => {
wrapper = shallow(<App />);
setState = jest.fn();
useStateSpy = jest.spyOn(React, "useState");
useStateSpy.mockImplementation(init => [init, setState]);
});
afterEach(() => jest.clearAllMocks());
it("has a usernameinput component", () => {
expect(wrapper.find("UsernameInput").length).toBe(1);
});
it("has a joinWithUsername function", () => {
const usernameInput = wrapper.find("UsernameInput").props();
console.log(usernameInput.onSubmit);
expect(usernameInput.onSubmit).toBe(joinWithUsername);
});
it("connect to socket.io server", () => {
joinWithUsername("Bobby");
expect(io).toHaveBeenCalledWith("http://localhost:3001");
});
it("emits the USER_JOIN event", () => {
joinWithUsername("John");
const socket = io();
expect(socket.emit).toHaveBeenCalledWith(eventTypes.USER_JOIN, {
username: "John"
});
});
it("listens for the MESSAGE event", () => {
joinWithUsername("John");
const socket = io();
expect(socket.on).toHaveBeenCalledWith(eventTypes.MESSAGE, messageListener);
});
it("Appends a message to state when message is received", () => {
const testData = {
from: "John",
message: "Hello everyone!"
};
messageListener(testData);
expect(setState).toHaveBeenCalledWith(testData); //ReferenceError: setMessages is not defined
});
});