Javascript 具有异步函数的有状态React组件未能通过Jest测试
在这件事上,我一直在跟进。我写的代码和作者完全一样,但由于某种原因,我的测试没有通过 我对作者回购的请求: 我有一个简单的React组件,它通过对Javascript 具有异步函数的有状态React组件未能通过Jest测试,javascript,reactjs,unit-testing,testing,jestjs,Javascript,Reactjs,Unit Testing,Testing,Jestjs,在这件事上,我一直在跟进。我写的代码和作者完全一样,但由于某种原因,我的测试没有通过 我对作者回购的请求: 我有一个简单的React组件,它通过对componentDidMount中的服务的异步/等待调用来更新它的count状态 {this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'} 预期 由于我模拟了NotificationsService,并将count设置为42,因此测试
componentDidMount
中的服务的异步/等待调用来更新它的count
状态
{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'}
预期
由于我模拟了NotificationsService,并将count设置为42
,因此测试应该通过,组件中的文本为“42个通知等待!”
结果
文本保持为默认的加载…
我已经正确地模拟了服务,count
变量甚至被正确地记录为42
!但是,this.state.count
仍然是-1
,因此它不会显示等待的${this.state.count}通知,而是显示加载…
,因此测试失败
我试过的
1) 我已经试着在延迟中增加1000
2) 尝试在测试中使用setTimeout
3) 尝试jest.useFakeTimers()代码>和jest.runAllTimers()代码>
但是没有任何工作,组件内部的计数
卡在-1
上,即使计数
设置为42。在我看来,我的测试是在状态设置完成之前运行的
NotificationsViewser.jsx组件
模拟:NotificationsService.js
最后
测试
从“React”导入React;
从“反应测试渲染器”导入渲染器;
“redux saga”的导入延迟;
从“../NotificationsViewer”导入NotificationsViewer;
jest.mock('../../services/NotificationsService');
const notificationService=require('../../services/NotificationsService')。默认值;
描述('通知查看器',()=>{
以前(()=>{
通知服务。设置计数(42);
});
它('应该显示正确的通知数',async()=>{
常量树=渲染器
.创造(
);
等待延迟();
const instance=tree.root;
const component=instance.findByProps({className:`notifications`});
const text=component.children[0];
log('文本为:',文本);
expect(text).toEqual('42个等待通知!');
});
})
也许您的描述
也需要是一个异步函数await
语句需要在async
范围内声明,否?问题在于await delay()
无法让所有React生命周期方法(如componentDidMount
实例化/调用)
我不得不使用Enzyme
,尽管由于存在许多公开的bug问题,作者不推荐使用它
使用Enzyme,我可以确保调用组件didmount
,从而使用模拟服务将count
的状态设置为42
我还需要安装以下软件包:
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
固定测试
从“React”导入React;
从“反应测试渲染器”导入渲染器;
从'enzyme-Adapter-react-16'导入适配器;
从“酶”导入{shallow,configure};
配置({adapter:newadapter()});
从“./NotificationsViewer”导入NotificationsViewer;
jest.mock(“../services/NotificationsService”);
const notificationService=require('../services/NotificationsService')。默认值;
notificationService.default=jest.fn();
描述('通知查看器',()=>{
以前(()=>{
通知服务。设置计数(42);
});
//它('pass',()=>{});
它('应该显示正确的通知数',async()=>{
常量树=renderer.create();
常量包装器=浅();
const instance=tree.root;
等待包装器.instance().componentDidMount();
const component=instance.findByProps({className:`notifications`});
const text=component.children[0];
log('文本为:',文本);
expect(text).toEqual(“等待42份通知”);
});
})
事实上,真正的问题在于同构react/src/components/\uuuu tests\uuuu/NotificationsViewer.js
文件。延迟
以错误的方式导入,导致测试错误
如果像这样导入delay
:import{delay}来自'redux saga'
修复问题=D好的,所以我刚试过,但得到了这个警告>不支持从“描述”返回承诺。测试必须同步定义。在Jest.Ops的未来版本中,从“descripe”返回一个值将使测试失败,我错过了it
块上的async
。在我看来,wait delay()
在测试expect
块之前不允许先运行生命周期方法。因为console.log的结果('text为:',text)首先命中code>,然后命中componentDidMount
和componentDidUpdate
日志。这是正确的,我的导入错误。然而,将我下面的答案作为处理这个问题的首选方法,因为不是每个项目都会使用redux saga
,我的示例解释了如何使用酶来解决这个问题:)
import { delay } from 'redux-saga';
export default {
async GetNotifications() {
console.warn("REAL NOTIFICATION SERVICE! CONTACTING APIS!");
await delay(1000);
return { count: 42 };
}
}
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!');
});
})
"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');
});
})