如何使用React Native Testing Library测试Yup .test()异步校验方法
解决方案
下面是导致问题的几个核心原因及对应修改方式:
1. 修复Yup异步校验函数的this指向问题
这是最核心的故障原因:你在Yup的test方法中使用了箭头函数作为校验回调,箭头函数没有独立的this指向,无法拿到Yup的test上下文,导致this.createError调用直接报错,而你代码中catch块没有做任何错误处理,错误被静默吞掉,Yup会认为校验通过,自然不会展示错误。
将Schema中的test回调修改为普通函数即可:
const schema = yup.object().shape({ username: Yup.string() .required('必填') .min(3, '长度过短') .max(15, '长度过长') .matches(/^[A-Za-z0-9_-]*$/, '不允许特殊符号') .test( 'unique-username', '用户名已被使用', // 替换箭头函数为普通function async function (value: string | undefined) { if(value){ try { const res = await checkUserHandleExist(value); const data = res.data; if (data.error) { return this.createError({message: "校验用户名时出错"}); } else { if (data.is_user_handle_exists) { return this.createError({message: "用户名已被使用"}); } return true; } } catch (error) { return this.createError({message: "校验用户名时出错"}); } } return true; } ) })
2. 补全测试中的事件触发逻辑
Formik默认的异步校验触发时机是输入框失焦时,你当前测试代码只触发了changeText输入事件,没有触发失焦事件,异步校验根本不会执行。输入完成后补充失焦触发:
fireEvent.changeText(usernameField, 'kenchoong') // 新增失焦事件,触发异步校验 fireEvent.blur(usernameField)
3. 等待异步流程执行完成
异步校验需要等待接口请求、校验逻辑执行、页面渲染的完整流程,不能用同步的queryByText立刻查询结果,换成自带等待能力的findByText即可:
// findByText默认最长等待1秒,会自动轮询查询元素 const errorMsg = await findByText(/用户名已被使用/i) expect(errorMsg).toBeTruthy()
如果你偏好使用waitFor,写法如下:
await waitFor(() => { expect(getByText(/用户名已被使用/i)).toBeTruthy() })
4. 确认Mock接口配置正确
如果你使用MSW做接口Mock,需要确认Mock的请求方法、路径、参数和checkUserHandleExist实际发起的请求完全一致,避免Mock未命中导致接口请求失败被catch吞掉,校验直接通过。可以在校验函数中加日志确认是否拿到了Mock返回的is_user_handle_exists: true结果。
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

