gpt4 book ai didi

javascript - 如何在 react 异步调用后测试状态更新和组件重新渲染

转载 作者:行者123 更新时间:2023-11-30 19:07:26 26 4
gpt4 key购买 nike

我正在编写一个简单的应用程序,点击按钮后,应该执行对 spotify API 的异步调用,当 promise 解析时,它应该更新组件的状态。我正在使用 React Hooks 来管理组件中的状态。

在我的测试中,我模拟了 API 调用。

spotify.jsx

export default class Spotify {
constructor(token) {
this.axiosInstance = axios.create({
baseURL: baseURL,
headers: buildHeaders(token),
});
}

async getUserInfo() {
const userInfo = await this.axiosInstance({
url: `/me`,
});
return userInfo.data
}
}

Spotify 模拟:

const getUserInfoMock = jest.fn();

const mock = jest.fn().mockImplementation(() => ({
getUserInfo: getUserInfoMock,
}));

export default mock;

用户.jsx

const User = props => {
const [user, setUser] = useState(null);
const {token} = useContext(AuthContext);
const spotify = useMemo(() => new Spotify(token), [token]);

const getUserInfo = async () => {
console.log("button clicked")
const fetched = await spotify.getUserInfo();
console.log(fetched)
setUser(fetched);
}

return (
<React.Fragment>
<p>user page</p>
<button onClick={getUserInfo} > click me </button>
{user && (
<div>
<p>{user.display_name}</p>
<p>{user.email}</p>
</div>
)}
</React.Fragment>
);
};

我的问题是如何正确测试此类行为。我设法让它通过了,但没有调用 awaitsimulate()一个丑陋的黑客?模拟不返回 promise 。这是一个测试:

  it('updates display info with data from api', async () => {
const userInfo = {
display_name: 'Bob',
email: 'bob@bob.bob',
};
spotifyMock.getUserInfo.mockImplementation(() => Promise.resolve(userInfo));

wrapper = mount(<User />);
expect(wrapper.find('p')).toHaveLength(1);
await wrapper
.find('button')
.last()
.simulate('click');

wrapper.update();
expect(wrapper.find('p')).toHaveLength(3);
});

另一方面,当我只检查 mock 是否被调用时,我不需要使用 async/await 和测试通过:

  it('calls spotify api on click', () => {
wrapper = mount(<User />);
expect(spotifyMock.getUserInfo).not.toHaveBeenCalled();
wrapper
.find('button')
.last()
.simulate('click');
expect(spotifyMock.getUserInfo).toHaveBeenCalledTimes(1);
});

我想知道我的测试方式是否正确,如果我想添加一个功能以在组件呈现时从 api 获取数据怎么办 - 使用 useEffect Hook 。 Enzyme 是否完全支持 React Hooks?我也在努力警告 Warning: An update to User inside a test was not wrapped in act(...)即使我包装 mountsimulate功能。

最佳答案

您应该根据 Dan Abramov's blog post 将影响渲染的调用包装在异步 act() 函数中像这样:

  it('calls spotify api on click', async () => {
await act(async () => {
wrapper = mount(<User />);
});
expect(spotifyMock.getUserInfo).not.toHaveBeenCalled();

await act(async () => {
wrapper
.find('button')
.last()
.simulate('click');
});

wrapper.update();
expect(spotifyMock.getUserInfo).toHaveBeenCalledTimes(1);
});

关于javascript - 如何在 react 异步调用后测试状态更新和组件重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58844251/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com