Cypress测试Mock useTranslation钩子失败,求问题排查
关于React-Intl翻译组件的Cypress测试失败问题
组件代码(EmailSignUpView)
import { useTranslation as t } from '@utils/hooks'; <div className={styles.notifyContainer}> <div className={styles.notifyTextContainer}> <h2 className={styles.signUpheading} data-test-id="email-signup-heading" > {t('email_stay_in_touch')} </h2> </div> </div>
useTranslation钩子实现
import { useIntl } from 'react-intl'; const useTranslation = ( id: string, values?: Record<string, string | number> ): string => { const { formatMessage } = useIntl(); return formatMessage({ id }, values); }; export default useTranslation;
Cypress测试代码
import { IntlProvider } from 'react-intl'; import EmailSignUpView from '@components/EmailSignUpView/EmailSignUpView'; import MockRouter from '../../cypress/support/utils'; import { enTransMessages } from '../../cypress/support/testData/testData'; import * as hooks from '@utils/hooks'; describe('Email Signup Section tests', () => { before(() => { // Stub the useTranslation hook cy.stub(hooks, 'useTranslation').callsFake(() => ({ t: (key) => { const translations = { 'email_stay_in_touch': 'The text that I want to test!', // Add other key-value pairs as needed }; return translations[key] || key; }, })); }); it('validate default Heading', () => { cy.mount( <MockRouter> <IntlProvider locale="en" messages={enTransMessages}> <EmailSignUpView /> </IntlProvider> </MockRouter> ); cy.getByDataID(selectors.heading) .should('have.text', 'The text that I want to test!') .and('be.visible'); }); });
测试日志
Type Function Alias(es) # Calls stub-1 useTranslation - spy-1 push - spy-2 replace - spy-3 reload - spy-4 back - spy-5 forward - stub-2 prefetch 2 spy-6 beforePopState - spy-7 emit - spy-8 off - spy-9 on -
错误原因分析
你对useTranslation的stub实现和实际钩子的调用逻辑完全不匹配:
- 实际的
useTranslation是接收id参数并直接返回字符串的函数,组件中{t('email_stay_in_touch')}直接调用该函数获取翻译文本。 - 但测试里的stub返回了一个包含
t方法的对象,导致组件调用t('xxx')时,实际是把这个对象当作函数执行,最终渲染结果不符合预期(通常会显示[object Object]或报错)。
修正方案
修改stub的callsFake逻辑,让它匹配实际钩子的函数签名和返回值类型:
before(() => { cy.stub(hooks, 'useTranslation').callsFake((id, values) => { const translations = { 'email_stay_in_touch': 'The text that I want to test!', }; // 若需要处理插值,可在这里结合values参数替换文本占位符 return translations[id] || id; }); });
调整后stub的行为和实际钩子一致,组件能正确获取测试用的翻译文本,测试即可通过。
内容的提问来源于stack exchange,提问作者JeffChen
相关产品推荐
相关产品推荐

