我刚刚开始为我的React应用程序探索一个单元测试框架。我将选择锁定在@testing-library/react
上,而不是React推荐的Enzyme
上,这有助于编写更可靠的测试。我还打算使用Jest
进行完整性检查。
但是在继续进行React Testing Library
之前,我陷入了几个问题。有人可以帮忙吗?
例如,
Editor
组件,可根据用户输入更新Redux存储。Preview
,它直接从存储中读取值。Container
,其中包含上述两个通过一些道具的部分。问题:
Editor
组件中输入的内容实际上是否更新商店?Preview
组件是否可以呈现从商店读取的值?Container
组件是否正确地将props传递给它的子代?Container.jsx
import React from 'react';
import Editor from './Editor';
import Preview from './Preview';
const Container = ({editorType}) => {
return (
<div>
<Editor type={editorType} />
<Preview />
</div>
);
};
export default Container;
Editor.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {setName} from './actions';
const Editor = ({type}) => {
const name = useSelector(state => state.name);
const dispatch = useDispatch();
return (
<div>
<h1>Type: {type}</h1>
<input value={name} onChange={evt => dispatch(setName(evt.target.value))} />
</div>
);
};
export default Editor;
Preview.jsx
import React from 'react';
import { useSelector } from 'react-redux';
const Editor = ({type}) => {
const name = useSelector(state => state.name);
return (
<div>
<h1>Name: {name}</h1>
</div>
);
};
export default Preview;
这是我的处理方式:
如何测试编辑器组件中的用户输入是否实际更新商店?
查看您的代码,编辑器不会更新存储,它不会调用useDispatch。但是假设这样做,我将使用https://github.com/reduxjs/redux-mock-store为测试中的组件设置一个模拟商店提供程序,然后触发用户输入并检查该模拟商店是否已分派了正确的操作以及正确的有效载荷:
describe('<Editor />', () => {
let store: MockStoreEnhanced;
let rtl: RenderResult;
beforeEach(() => {
store = mockStore({ /* your store structure */ });
rtl = render(
<Provider store={store}>
<Editor type={...} />
</Provider>
);
});
test('dispatch action correctly', () => {
fireEvent.change(rtl.container.querySelector('input'), { target: {value: 'test' } });
// check actions that were dispatched by change event
// getActions return an array avec redux actions (type, payload)
expect(store.getActions()).toEqual(...);
}
}
此外,您还应该测试商店缩减工具和动作创建者,以确保动作正确地修改了商店。
如何测试预览组件是否可以呈现从商店读取的值?
相同的原理,使用模拟商店设置测试,使用相关值初始化该商店,然后测试组件是否显示商店中的内容:
describe('<Preview />', () => {
let store: MockStoreEnhanced;
let rtl: RenderResult;
beforeEach(() => {
store = mockStore({ name: 'This is name from store' });
rtl = render(
<Provider store={store}>
<Preview type={...} />
</Provider>
);
});
test('displays store content correctly', () => {
expect(rtl.getByText('This is name from store')).toBeTruthy();
}
}
如何测试容器组件是否正确地将道具传递给子组件?
在这里,您应该一起测试Container + Preview + Editor,并找到可视化的东西进行测试(就像真实用户会看到的一样),其中涉及Container传递给其子级的道具。
例如,如果预览显示props.type,它来自Container editorType props:
describe('<Container />', () => {
// mocked store may not be necessary here, depending on your use case
let store: MockStoreEnhanced;
let rtl: RenderResult;
beforeEach(() => {
store = mockStore({ name: 'This is name from store' });
rtl = render(
<Provider store={store}>
<Container editorType={'toTest'} />
</Provider>
);
});
test('displays store content correctly', () => {
// check that 'toTest' exists in DOM because it is rendered by Preview component, a child of Container
expect(rtl.getByText('toTest')).toBeTruthy();
}
}
总结起来,我的方法是:
对于最后两个项目,我使用https://github.com/reduxjs/redux-mock-store。