如何Mock RTK Query登录端点并验证提交触发调用?解决函数类型错误
问题解答
是否需要测试登录端点的调用情况?
需要。表单组件的核心职责就是收集用户输入并触发登录请求,验证这一行为能确保组件正确履行功能,避免出现输入合法但未发起请求的异常情况。
错误原因与Mock方案
你遇到的received value must be a mock or spy function错误,是因为你尝试断言的是RTK Query提供的真实mutation函数,而非可追踪的mock/spy函数。要解决这个问题,只需Mock useLoginMutation Hook,让它返回可监控的mock函数即可。
具体实现步骤
- 在测试文件中Mock
useLoginMutation
import { authApiSlice } from '../path/to/authApiSlice'; // Mock整个模块,保留其他导出内容,仅替换useLoginMutation为mock函数 jest.mock('../path/to/authApiSlice', () => ({ ...jest.requireActual('../path/to/authApiSlice'), useLoginMutation: jest.fn(), }));
- 在测试用例中配置Mock返回值
根据测试场景(比如登录失败),让Mock的Hook返回符合RTK Query规范的结构:包含mock的mutate函数,以及对应的状态信息。
test('Submitting the form with wrong username', async () => { // 创建mock的mutate函数,模拟登录失败的响应 const mockMutate = jest.fn().mockRejectedValue({ data: { message: 'username or password is incorrect' }, }); // 设置useLoginMutation的返回值,匹配RTK Query Hook的返回结构 (authApiSlice.useLoginMutation as jest.Mock).mockReturnValue([ mockMutate, { isError: true, error: { data: { message: 'username or password is incorrect' } } }, ]); const { getByTestId, findByText } = render(<Form />); // 模拟用户输入 fireEvent.input(getByTestId('usernameField'), { target: { value: 'example' } }); fireEvent.input(getByTestId('passwordField'), { target: { value: '1212' } }); // 模拟表单提交 fireEvent.submit(getByTestId('submitBtn')); // 验证原有断言逻辑 expect(await findByText(/username or password is incorrect/i)).toBeInTheDocument(); expect(getByTestId('usernameField')).toHaveValue(''); expect(getByTestId('passwordField')).toHaveValue(''); // 新增:验证登录端点被正确调用,且参数匹配用户输入 expect(mockMutate).toHaveBeenCalledWith({ username: 'example', password: '1212', }); });
注意事项
- 确保你的
Form组件内部是通过useLoginMutation获取mutate函数并调用的,这样Mock才能生效。 - 若需测试登录成功场景,只需将
mockRejectedValue替换为mockResolvedValue,并调整状态对象为{ isSuccess: true }即可。 - 你当前使用的
AllTheProviders中的真实store不会影响Mock效果,因为组件会优先使用Mock后的Hook。
内容的提问来源于stack exchange,提问作者Maksim Ostroginskiy
相关产品推荐
相关产品推荐

