使用 test 和 react-testing-library 测试反应组件
Test a react component using test and react-testing-library
我刚刚加入了一个团队,我们使用 react、redux、recompose 构建组件来构建 UI。应用程序中没有任何单元测试,应用程序也没有一致的架构。我决定自己使用 jest 和 react-testing-library 添加单元测试。我成功地完成了很少的快照测试,但我在单元测试中苦苦挣扎。我仍在学习反应并且对 redux 还很陌生。我会喜欢一些建议。我将共享一个组件,该组件呈现带有列和行的 table。我希望得到反馈。
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);
我通常从一个简单的 "should render without crashing" 测试开始。我更喜欢导出和测试未修饰的组件,在你的例子中 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()}
/>
);
});
});
此时我 运行 一个代码覆盖率报告来查看我有多少,然后添加更多具有不同属性值的测试 and/or 使用 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(
<Contacts
// pass all the props necessary for a basic render
clearAll={jest.fn()}
fetchContacts={jest.fn()}
intl={intlMock}
/>,
{
wrapper: IntlWrapper
}
);
react-testing-library
有很多文档,但值得一读。希望这能帮助你开始。
我刚刚加入了一个团队,我们使用 react、redux、recompose 构建组件来构建 UI。应用程序中没有任何单元测试,应用程序也没有一致的架构。我决定自己使用 jest 和 react-testing-library 添加单元测试。我成功地完成了很少的快照测试,但我在单元测试中苦苦挣扎。我仍在学习反应并且对 redux 还很陌生。我会喜欢一些建议。我将共享一个组件,该组件呈现带有列和行的 table。我希望得到反馈。
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);
我通常从一个简单的 "should render without crashing" 测试开始。我更喜欢导出和测试未修饰的组件,在你的例子中 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()}
/>
);
});
});
此时我 运行 一个代码覆盖率报告来查看我有多少,然后添加更多具有不同属性值的测试 and/or 使用 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(
<Contacts
// pass all the props necessary for a basic render
clearAll={jest.fn()}
fetchContacts={jest.fn()}
intl={intlMock}
/>,
{
wrapper: IntlWrapper
}
);
react-testing-library
有很多文档,但值得一读。希望这能帮助你开始。