Jest登录单元测试异常:Login API未返回Promise问题排查
登录页面单元测试问题排查:调用login API未返回Promise导致流程中断
我开发的登录页面功能正常,但使用Jest编写该模块单元测试时出现问题:调用login API未返回Promise,导致无法打印console.log("after login");日志,后续流程也无法执行。以下是相关代码:
React业务代码
validateAll(formData, rules, message).then(async () => { dispatch(setLoading(true)) console.log("before login"); const login = await authApi.login(app, email, password) console.log("after login"); if (login && login.error && login.error !== null) { dispatch(setLoading(false)) ToastAlert({ msg: login.error.error || login.error.message, msgType: 'error' }); dispatch(setToken('')) } else { console.log("done"); dispatch(setToken(login.data._accessToken)) setSuccess(true) dispatch(setLoading(false)) //router.replace("/"); ToastAlert({ msg: 'You have successfully logged in', msgType: 'success' }); } })
authApi代码
import { resolve } from "./resolve"; import * as Realm from "realm-web"; function auth() { const register = async (app: any, data: object) => { return await resolve( app.emailPasswordAuth.registerUser(data) .then((response: any) => response) ) } const login = async (app: any, email: string, password: string) => { const credentials = await Realm.Credentials.emailPassword(email, password); return await resolve( app.logIn(credentials) .then((response: any) => response) ) } const confirmUser = async (app: any, data: object) => { return await resolve( app.emailPasswordAuth.confirmUser(data) .then((response: any) => response) ) } const logout = async (app: any) => { return await resolve( app.currentUser.logOut() .then((response: any) => response) ) } return { register, login, confirmUser, logout } } const authApi = auth(); export default authApi;
Jest测试代码
test('login with correct username and password', async () => { const initialState = { email: '', password: '', error: { email: "", password: "" }, }; const mockStore = configureStore(); let store; store = mockStore(initialState); const { getByText,getByLabelText } = render( <Provider store={store}> <Authenticate /> </Provider> ); // fill out the form fireEvent.change(screen.getByLabelText('Email'), { target: {value: '***@gmail.com'}, }) fireEvent.change(screen.getByLabelText(/Parola/i), { target: {value: '****@123'}, }) const loginAwait = screen.getByText(/Authentificare/i); await fireEvent.click(loginAwait) // wait for the error message const alert = await screen.findByRole('alert') expect(alert).toHaveTextContent(/You have successfully logged in/i) })
解决方案
1. Mock authApi的login方法
测试中不要调用真实的Realm API,而是mock authApi模块,让login方法返回一个已resolve的Promise,模拟成功场景:
// 在测试文件顶部引入并mock import authApi from '../path/to/authApi'; jest.mock('../path/to/authApi', () => ({ login: jest.fn().mockResolvedValue({ data: { _accessToken: 'mock-token' } }) }));
注意替换../path/to/authApi为实际文件路径。
2. 确保异步流程被正确等待
fireEvent.click不会等待内部异步操作完成,建议结合waitFor来等待UI更新:
fireEvent.click(loginAwait); // 等待alert出现并验证内容 await waitFor(() => { expect(screen.getByRole('alert')).toHaveTextContent(/You have successfully logged in/i); });
3. 检查resolve函数的实现
确认resolve函数正确封装Promise,确保它返回Promise对象,示例正确实现:
// resolve.js export function resolve(promise) { return promise .then(data => ({ data })) .catch(error => ({ error })); }
如果resolve函数没有正确返回Promise,会导致await authApi.login()无法等待结果。
4. 验证mock调用是否生效
添加断言确保login方法被正确调用:
// 在测试末尾添加 expect(authApi.login).toHaveBeenCalledWith( expect.anything(), '***@gmail.com', '****@123' );
内容的提问来源于stack exchange,提问作者Nikul Panchal
相关产品推荐
相关产品推荐

