javascript - 具有异步功能的有状态 React 组件未通过 Jest 测试
问题描述
我正在关注Pluralsight 的这个 Jest 测试教程。而且我写的代码和作者一模一样,但是由于某种原因我的测试没有通过。
我对作者仓库的拉取请求:https ://github.com/danielstern/isomorphic-react/pull/19
我有一个简单的 React 组件,它count
通过对componentDidMount
.
{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'}
预期的
由于我已经模拟了 NotificationsService,并将 count 设置为42
,因此测试应该通过组件内的文本"42 Notifications Awaiting!"
结果
文本保持为默认值Loading...
我已经正确地模拟了服务,并且count
变量甚至被正确记录为42
!然而this.state.count
仍然-1
如此,而不是显示:${this.state.count} Notifications Awaiting
它仍然显示Loading...
,因此测试失败。
我试过的
1)我尝试在延迟中添加 1000。
2) 尝试在测试中使用 setTimeout。
3)尝试jest.useFakeTimers();
和jest.runAllTimers();
但是没有任何效果,即使设置为 42,count
组件的内部也会卡住。在我看来,我的测试在状态设置完成之前正在运行?-1
count
NotificationsViewser.jsx 组件
import React from 'react';
import NotificationsService from '../services/NotificationsService';
export default class componentName extends React.Component {
constructor(...args) {
super(...args);
this.state = {
count: -1
}
}
async componentDidMount () {
let { count } = await NotificationsService.GetNotifications();
console.log('count:', count);
this.setState({
count
});
}
componentDidUpdate() {
console.log('componentDidUpdate:', this.state);
}
render() {
return (
<div className="mt-3 mb-2">
<div className="notifications">
{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : `Loading...`}
</div>
</div>
)
}
}
NotificationsService.js
import { delay } from 'redux-saga';
export default {
async GetNotifications() {
console.warn("REAL NOTIFICATION SERVICE! CONTACTING APIS!");
await delay(1000);
return { count: 42 };
}
}
模拟:NotificationsService.js
let count = 0;
export default {
__setCount(_count) {
count = _count;
},
async GetNotifications() {
console.warn("GOOD JOB! USING MOCK SERVICE");
return { count };
}
}
最后...
考试
import React from 'react';
import renderer from 'react-test-renderer';
import delay from 'redux-saga';
import NotificationsViewer from '../NotificationsViewer';
jest.mock('../../services/NotificationsService');
const notificationService = require('../../services/NotificationsService').default;
describe('The notification viewer', () => {
beforeAll(() => {
notificationService.__setCount(42);
});
it('should display the correct number of notifications', async() => {
const tree = renderer
.create(
<NotificationsViewer/>
);
await delay();
const instance = tree.root;
const component = instance.findByProps({className: `notifications`});
const text = component.children[0];
console.log('text is:', text);
expect(text).toEqual('42 Notifications Awaiting!');
});
})
解决方案
问题是让所有 React 生命周期方法(如实例化/被调用)await delay()
都不起作用。componentDidMount
Enzyme
即使由于许多未解决的错误问题,作者不推荐它,我也不得不使用它。
使用 Enzyme 我可以确保componentDidMount
调用了 ,从而使用模拟服务设置count
to的状态。42
我还需要安装以下软件包:
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
固定测试
import React from 'react';
import renderer from 'react-test-renderer';
import Adapter from 'enzyme-adapter-react-16';
import { shallow, configure } from 'enzyme';
configure({adapter: new Adapter()});
import NotificationsViewer from './NotificationsViewer';
jest.mock('../services/NotificationsService');
const notificationService = require('../services/NotificationsService').default;
notificationService.default = jest.fn();
describe('The notification viewer', () => {
beforeAll(() => {
notificationService.__setCount(42);
});
// it('pass', () => {});
it('should display the correct number of notifications', async() => {
const tree = renderer.create(<NotificationsViewer />);
const wrapper = shallow(<NotificationsViewer />);
const instance = tree.root;
await wrapper.instance().componentDidMount();
const component = instance.findByProps({className: `notifications`});
const text = component.children[0];
console.log('text is:', text);
expect(text).toEqual('42 Notifications Awaiting');
});
})
推荐阅读
- android - Android NDK:无法在 64 位设备上加载 arm64-v8a
- angular - 带有角度 5 中添加/编辑/删除标题选项的日历组件
- ruby-on-rails - 在跟踪变量 n 的方法中创建循环
- django - Django:基于外键获取多个项目的有效方法
- c# - 如何解决 IronPython 错误
- java - 请求处理失败;嵌套异常是 org.hibernate.MappingException: Unknown entity
- python - Python:获取下一个工作时间段
- c# - Windows 服务不会循环写入日志文件
- dynamic-programming - 斐波那契记忆执行顺序
- sql - 我可以对 Accept 命令使用 IF 语句吗