集成测试时如何模拟用户登录状态?

上官一莹 阅读 11

我在写前端集成测试,用的是 Jest + React Testing Library。现在有个组件依赖用户是否已登录,但不知道怎么在测试里模拟登录状态。

试过直接 mock localStorage,但组件里是通过 API 调用获取用户信息的,而且用了 async/await。测试总是跑太快,拿不到数据。

比如这个调用:

const user = await fetchUser()

我该怎么 mock 这个 fetchUser 函数,让它在测试中返回一个假的用户对象?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
司空梓涵
这个问题挺常见的,mock async 函数其实不难,关键是得用 jest.mock 配合 mockResolvedValue 或者 mockResolvedValueOnce

假设你的 fetchUser 是从某个 api 文件导出的,大概长这样:

// api.js
export const fetchUser = async () => {
const res = await fetch('/api/user');
return res.json();
};


那测试文件里这样写就行:

// MyComponent.test.js
import { render, screen, waitFor } from '@testing-library/react';
import MyComponent from './MyComponent';
import { fetchUser } from './api';

// 这一步很关键,mock 整个模块
jest.mock('./api');

test('显示用户信息', async () => {
// mock 返回值
fetchUser.mockResolvedValue({ id: 1, name: '测试用户', loggedIn: true });

render();

// 因为是异步的,得等一下
await waitFor(() => {
expect(screen.getByText('测试用户')).toBeInTheDocument();
});
});


有几个点要注意下。JS里面 jest.mock 会被提升到文件顶部执行,所以不管你写在哪行,它都会先于 import 执行,这点挺方便的。

如果你需要不同的测试用例返回不同的值,可以用 mockResolvedValueOnce

fetchUser
.mockResolvedValueOnce({ id: 1, name: '用户A' })
.mockResolvedValueOnce({ id: 2, name: '用户B' });


另外你说测试跑太快拿不到数据,这其实不是 mock 的问题,是因为你没用 waitFor 或者 findBy。React Testing Library 里处理异步状态,findBy* 系列方法自带等待机制,比 getBy*waitFor 写起来更简洁:

// 这样写也行,findBy 自带等待
const userName = await screen.findByText('测试用户');
expect(userName).toBeInTheDocument();


如果组件里还有其他异步逻辑,比如登录状态存在 Context 或者全局状态管理里,那可能还得配合 mock 一下 Context Provider,不过原理都是一样的。
点赞
2026-03-01 17:05