使用React Testing Library测试登录功能时mock的signIn未触发如何解决
问题根因与修复方案
你遇到的报错由4个独立问题共同导致,按优先级排序修复即可:
1. Mock函数配置错误
你当前定义的signIn是普通函数,没有Jest的调用追踪能力,toHaveBeenCalledTimes断言对普通函数无效,且未适配组件中await调用的异步逻辑。
修复后的Mock写法:
jest.mock("next-auth/client", () => ({ signIn: jest.fn(() => Promise.resolve({ ok: true })) }))
如果要测试登录失败场景,可修改Mock返回值为Promise.resolve({ ok: false, error: "邮箱未找到" })。
2. 未等待异步操作完成就执行断言
user.type、表单提交、signIn调用全是异步逻辑,你点击按钮后直接断言,此时异步逻辑还未执行完毕,signIn自然还没被调用。
修复方案:
给所有user-event交互加await,断言用waitFor包裹等待异步执行完成。
3. Form组件Prop接收逻辑错误(组件本身Bug)
你在SignIn组件中给Form传的是onSubmit={validateEmail},但Form组件解构的是{ validateEmail },等于完全没拿到父组件传的提交方法;且Form中判断提交按钮渲染的条件是{onSubmit && ...},但你根本没有接收onSubmit这个Prop,导致按钮不会渲染、就算找到按钮提交时也会因为调用undefined直接报错,走不到signIn逻辑。
修复后的Form组件参数:
const Form = ({ onSubmit: validateEmail, children }) => { // 其余逻辑保持不变 }
4. 修正后的完整测试代码
import "@testing-library/jest-dom" import { configure, fireEvent, render, waitFor } from "@testing-library/react" import user from "@testing-library/user-event" import { signIn } from "next-auth/client" import React from "react" import SignIn from "../../pages/auth/sign-in" jest.mock("next-auth/client", () => ({ signIn: jest.fn(() => Promise.resolve({ ok: true })) })) test("signs in successfully", async () => { const validEmail = "validemail@test.com" const { getByTestId, getByText } = render(<SignIn />) const emailInput = getByTestId(/email/i) const signInButton = getByText(/sign in/i) // 等待输入完成 await user.type(emailInput, validEmail) fireEvent.click(signInButton) // 等待异步调用完成再断言 await waitFor(() => { expect(signIn).toHaveBeenCalledTimes(1) expect(signIn).toHaveBeenCalledWith("email", { email: validEmail }) }) })
内容的提问来源于stack exchange,提问作者hungry
相关产品推荐
相关产品推荐

