问题描述
我正在尝试存根/监视翻译,而不仅仅是嘲笑它,即使在这种最基本的情况下,我似乎也无法触发它.
/*** 组件名称.jsx*/import { useTranslation } from react-i18next";导出默认函数 ComponentName() {const { t } = useTranslation();return t(`index:path`)}/*** 组件名称.test.jsx*/从酶"导入{浅};从./ComponentName"导入组件名称;import { useTranslation } from react-i18next";jest.mock(react-i18next", () => ({useTranslation: () =>({ t: jest.fn(key => key) })}));it(调用翻译函数", () => {const 包装器 = 浅(<组件名称/>);期望(useTranslation().t).toHaveBeenCalled();});
当我在 ComponentName.jsx 文件
中放入一个 console.log(t)
时,它正确地显示它是一个模拟函数.如果我将 t()
放在 ComponentName.test.jsx
文件中,它就会通过.
有没有办法存根,以便我最终可以用 toHaveBeenCalledWith
标记它?还是我被降级为对组件执行 contains("index:path")
?
所以,当我更新@felixmosh 的回答时
/*** 组件名称.test.jsx*/从'酶'导入{安装};从'react-i18next'导入{ I18nextProvider };describe('', () => {it('调度 SORT_TABLE', () => {const i18nextMock = {t: jest.fn(key => key),};const 酶包装器 = 安装(<I18nextProvider i18n={i18nextMock}><某些组件/></I18nextProvider>);期望(i18nextmock.t).toHaveBeenCalled()});});/*** 组件名称.jsx*/import { useTranslation } from react-i18next";导出默认函数 ComponentName() {const { t } = useTranslation();return t(`index:path`)}
同样的问题.如果 t
是 a string"
而不是 jest.fn()
,当我 console.log t
在 ComponentName.jsx
中,当我将 console.log t
作为 jest.fn(key=> 键)
,我正确地得到了一个函数.
但是当我调用它时,我不明白.
是否有可能发送到 I18nextProvider 的实例不是同一个实例?
2 你应该在代码中改进的地方:
useTransaltion
是一个需要context
的钩子,确保你用i18nextProvider
包裹你的组件.- 事实上,您将嵌套组件切换
shallow
和mount
. - 不需要模拟任何东西,
i18next
内置了对测试的支持.为了启用它,请使用cimode
作为lng
为测试配置i18next
时.
//i18nForTests.js从i18next"导入 i18n;从'react-i18next'导入{initReactI18next};i18n.use(initReactI18next).init({lng: 'cimode',//----- ^//有一个围绕完整应用程序使用的公共命名空间ns: ['翻译'],默认NS:'翻译',插值:{escapeValue: false,//不需要反应!!},资源:{ en:{ 翻译:{} } },});导出默认 i18n;
//SomeComponent.test.js从'酶'导入{安装};从'react-i18next'导入{ I18nextProvider };从 '../i18nForTests' 导入 i18n;describe('', () => {it('调度 SORT_TABLE', () => {const 酶包装器 = 安装(<I18nextProvider i18n={i18n}><某些组件/></I18nextProvider>);酶Wrapper.find('.sort').simulate('click');期望(enzymeWrapper.find('#some-text').text()).toEqual('MY_TRANS_KEY');});});
带有模拟 I18next 的版本
//i18nextMock.js导出 const i18nextMock = {t: jest.fn(),//对其他 i18next 字段执行相同操作};//SomeComponent.test.js从'酶'导入{安装};从'react-i18next'导入{ I18nextProvider };从'../i18nextMock'导入i18nextMock;describe('', () => {it('调度 SORT_TABLE', () => {const 酶包装器 = 安装(<I18nextProvider i18n={i18nextMock}><某些组件/></I18nextProvider>);酶Wrapper.find('.sort').simulate('click');期望(enzymeWrapper.find('#some-text').text()).toEqual('MY_TRANS_KEY');});});
I'm trying to stub/spy the translation, not just mock it, and I can't seem to get it to trigger even in this most base case.
/**
* ComponentName.jsx
*/
import { useTranslation } from "react-i18next";
export default function ComponentName() {
const { t } = useTranslation();
return <div>t(`index:path`)</div>
}
/**
* ComponentName.test.jsx
*/
import { shallow } from "enzyme";
import ComponentName from "./ComponentName";
import { useTranslation } from "react-i18next";
jest.mock("react-i18next", () => ({
useTranslation: () => ({ t: jest.fn(key => key) })
}));
it("calls the translation function", () => {
const wrapper = shallow(<ComponentName />);
expect(useTranslation().t).toHaveBeenCalled();
});
When I drop a console.log(t)
in the ComponentName.jsx file
, it correctly displays that it's a mocked function.If I put t()
in the ComponentName.test.jsx
file, it passes.
Is there a way to stub this so that I can eventually tag it with toHaveBeenCalledWith
? Or am I relegated to doing contains("index:path")
on the component?
Edit: So, when I updated on @felixmosh's answer
/**
* ComponentName.test.jsx
*/
import { mount } from 'enzyme';
import { I18nextProvider } from 'react-i18next';
describe('<SomeComponent />', () => {
it('dispatches SORT_TABLE', () => {
const i18nextMock = {
t: jest.fn(key => key),
};
const enzymeWrapper = mount(
<I18nextProvider i18n={i18nextMock}>
<SomeComponent />
</I18nextProvider>
);
expect(i18nextmock.t).toHaveBeenCalled()
});
});
/**
* ComponentName.jsx
*/
import { useTranslation } from "react-i18next";
export default function ComponentName() {
const { t } = useTranslation();
return <div>t(`index:path`)</div>
}
It's the same issue. If t
was "a string"
instead of jest.fn()
, when i console.log t
in ComponentName.jsx
, I correctly get "a string"
, when I console.log t
as jest.fn(key => key)
, I correctly get a function.
But when I call it, I don't get it.
Is it possible that it's not the same instance that's being sent to I18nextProvider?
2 Things that you should improve in your code:
useTransaltion
is a hook which requirescontext
, make sure you wrap you component withi18nextProvider
.- As of the fact you will have nested components switch
shallow
withmount
. - There is no need for mocking anything,
i18next
has a built-it support of tests.In order to enable it usecimode
as thelng
when configuring youri18next
for tests.
// i18nForTests.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
lng: 'cimode',
// ----- ^
// have a common namespace used around the full app
ns: ['translations'],
defaultNS: 'translations',
interpolation: {
escapeValue: false, // not needed for react!!
},
resources: { en: { translations: {} } },
});
export default i18n;
// SomeComponent.test.js
import { mount } from 'enzyme';
import { I18nextProvider } from 'react-i18next';
import i18n from '../i18nForTests';
describe('<SomeComponent />', () => {
it('dispatches SORT_TABLE', () => {
const enzymeWrapper = mount(
<I18nextProvider i18n={i18n}>
<SomeComponent />
</I18nextProvider>
);
enzymeWrapper.find('.sort').simulate('click');
expect(enzymeWrapper.find('#some-text').text()).toEqual('MY_TRANS_KEY');
});
});
Edit: Version with mocked I18next
// i18nextMock.js
export const i18nextMock = {
t: jest.fn(),
// Do the same for other i18next fields
};
// SomeComponent.test.js
import { mount } from 'enzyme';
import { I18nextProvider } from 'react-i18next';
import i18nextMock from '../i18nextMock';
describe('<SomeComponent />', () => {
it('dispatches SORT_TABLE', () => {
const enzymeWrapper = mount(
<I18nextProvider i18n={i18nextMock}>
<SomeComponent />
</I18nextProvider>
);
enzymeWrapper.find('.sort').simulate('click');
expect(enzymeWrapper.find('#some-text').text()).toEqual('MY_TRANS_KEY');
});
});
这篇关于在 Jest 中存根 I18next useTranslation 钩子不会触发 toHaveBeenCalled的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!