问题描述
我试图对翻译进行存根/间谍,而不仅仅是模拟它,即使在这种最基本的情况下,我似乎也无法触发它。
/ **
* ComponentName.jsx
* /
import {useTranslation}来自 react-i18next ;
导出默认函数ComponentName(){
const {t} = useTranslation();
return< div> t(ʻindex:path`)< / div>
}
/ **
* ComponentName.test.jsx
* /
从酶中导入{浅};
从 ./ComponentName导入ComponentName;
import {useTranslation} from react-i18next;
jest.mock( react-i18next,()=>({
useTranslation:()=>({t:jest.fn(key => key)})
}));
it(调用翻译函数,()=> {
const wrapper = shallow(< ComponentName />);
期望(useTranslation()。t).toHaveBeenCalled();
});
当我将 console.log(t)
放在 ComponentName.jsx文件
,它会正确显示它是一个模拟函数。
如果我将 t()
放在 ComponentName.test.jsx
文件中,它将通过。
是否有一种方法可以存根,以便最终使用 toHaveBeenCalledWith
对其进行标记?还是我被降级为对该组件执行 contains( index:path)
?
编辑:所以,当我更新@felixmosh的答案
/ **
* ComponentName.test .jsx
* /
从酶导入{mount};从 react-i18next导入
{I18nextProvider};
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;
导出默认函数ComponentName(){
const {t} = useTranslation();
return< div> t(ʻindex:path`)< / div>
}
这是同样的问题。如果 t
是字符串
而不是 jest.fn()
,当我在 ComponentName.jsx
中的console.log t
时,我正确地得到了字符串
,当我用 jest.fn(key => key)console.log
,我正确地获得了一个函数。 t
时
但是当我调用它时,却没有。
是
2应该在代码中改进的地方:
-
useTransaltion
是需要上下文
的钩子,请确保使用i18nextProvider
包装组件。 - 事实上,您将拥有嵌套的组件开关
浅
带有mount
。 - 无需嘲笑任何东西,
i18next
具有对测试的内置支持。
为了启用它,请使用作为lng
配置测试的i18next
时。
// i18nForTests.js
从'i18next'导入i18n;
从 react-i18next导入{initReactI18next;
i18n.use(initReactI18next).init({
lng:'cimode',
// ----- ^
//具有公共命名空间在整个应用程序中使用
ns:['translations'],
defaultNS:'translations',
插值:{
escapeValue:false,//不需要
},
资源:{zh:{翻译:{}}},
});
出口默认值i18n;
// SomeComponent.test.js
import'mount} from'enzyme';从 react-i18next导入
{I18nextProvider};
从 ../i18nForTests导入i18n;
describe('< SomeComponent />',()=> {
it('dispatches SORT_TABLE',()=> {
constaseWrapper =安装(
< I18nextProvider i18n = {i18n}>
< SomeComponent />
< / I18nextProvider>
);
enzymeWrapper.find('。 sort')。simulate('click');
Expect(enzymeWrapper.find('#some-text')。text())。toEqual('MY_TRANS_KEY');
} );
});
编辑:带有模拟的I18next的版本
// i18nextMock.js
导出常量i18nextMock = {
t:jest.fn(),
//对其他i18next字段
执行相同的操作};
// SomeComponent.test.js
从酶导入{mount};从 react-i18next导入
{I18nextProvider};
从 ../i18nextMock导入i18nextMock;
describe('< SomeComponent />',()=> {
it('dispatches SORT_TABLE',()=> {
constaseWrapper =安装(
< I18nextProvider i18n = {i18nextMock}>
< SomeComponent />
< / I18nextProvider>
);
aseWerapper.find('。 sort')。simulate('click');
Expect(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');
});
});
这篇关于暂存I18next useJest中的Translation钩子不会触发toHaveBeenCalled的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!