我刚刚加入一个团队,在这里我们使用react,redux,recompose来构建用于构建UI的组件。应用程序中没有任何单元测试,并且该应用程序没有一致的体系结构。我决定自己使用jest和react-testing-library添加单元测试。我通过少量快照测试获得了成功,但是我在单元测试方面苦苦挣扎。我仍在学习对Redux的反应和新手。我希望有一些建议。我将共享一个组件,该组件呈现具有列和行的表。我希望得到反馈。
import React, { useEffect, useState } from 'react';
import { compose } from 'recompose';
import { connect } from 'react-redux';
import { clearAll, fetchContacts } from '~/store/resources/contacts/actions';
import { isDevEnv } from '~/utils';
import Sidebar from './Sidebar';
import Table from './Table';
import Toolbar from './Toolbar';
const Contacts = ({ clearAll, fetchContacts, ...props }) => {
const [searchValue, setSearchValue] = useState('');
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [canonicalFormValues, setCanonicalFormValues] = useState({ active: true });
useEffect(() => {
fetchContacts();
return () => {
clearAll();
};
}, []);
const closeSidebar = () => {
if (isDevEnv) {
console.log('hit close function');
}
setIsSidebarOpen(false);
};
return (
<div>
<Toolbar
searchValue={searchValue}
setSearchValue={setSearchValue}
setIsSidebarOpen={setIsSidebarOpen}
/>
<Table setCanonicalFormValues={setCanonicalFormValues} />
<Sidebar
isSidebarOpen={isSidebarOpen}
closeSidebar={closeSidebar}
canonicalFormValues={canonicalFormValues}
/>
{isDevEnv && (
<div>
This is coming from the contact folder
<br />
state values:
<br />
{JSON.stringify({ searchValue })}
<br />
{JSON.stringify({ isSidebarOpen })}
<br />
{JSON.stringify({ canonicalFormValues })}
</div>
)}
</div>
);
};
const mapDispatchToProps = {
clearAll,
fetchContacts,
};
export default compose(
connect(
null,
mapDispatchToProps,
),
)(Contacts);
答案 0 :(得分:0)
我通常从一个简单的“应该呈现而不会崩溃”测试开始。对于您的Contacts
,我更喜欢导出并测试未修饰的组件。
export const Contacts = ({ clearAll, fetchContacts, ...props }) => { ...
在测试文件中
import React from 'react';
import { render } from '@testing-library/react';
import { Contacts } from '.';
// mock the other imported components, they should already be tested alone, right?
jest.mock('./Sidebar');
jest.mock('./Table');
jest.mock('./Toolbar');
describe('Contacts', () => {
it('should render without crashing', () = {
render(
<Contacts
// pass all the props necessary for a basic render
clearAll={jest.fn()}
fetchContacts={jest.fn()}
/>
);
});
});
这时,我运行一个代码覆盖率报告以查看我有多少,然后添加更多具有不同prop值的测试,和/或使用react-testing-library的匹配器将目标按钮或元素定位为断言文本可见或触发回调等,直到我想要的覆盖范围为止。
有时您的某些组件可能依赖于上下文提供程序,在这种情况下,RTL允许您指定包装器。例如,如果您的组件用react-intl
装饰以进行字符串本地化,则可以提供包装器。
export const Contacts = ({ clearAll, fetchContacts, intl }) => { ...
...
export default compose(
connect(
null,
mapDispatchToProps,
),
injectIntl,
)(Contacts);
创建包装器
import { IntlProvider } from 'react-intl';
const IntlWrapper = ({ children }) => (
<IntlProvider locale="en">{children}</IntlProvider>
);
const intlMock = {
...
formatMessage: message => message,
...
};
要进行测试,请在render options参数中指定包装器
render(
<Contacts
// pass all the props necessary for a basic render
clearAll={jest.fn()}
fetchContacts={jest.fn()}
intl={intlMock}
/>,
{
wrapper: IntlWrapper
}
);
react-testing-library
有很多文档,但是值得通读。希望这对您有所帮助。