Я слежу за этим Учебное пособие по тесту Jest на Pluralsight здесь. И я написал код точно так же, как автор, но мой тест почему-то не проходит.
Мой запрос на включение в репозиторий автора: https://github.com/danielstern/isomorphic-react/pull/19
У меня есть простой компонент React, он обновляет свое состояние count с помощью асинхронного/ожидающего вызова службы в componentDidMount.
{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'}
Поскольку я издевался над NotificationsService и установил для счетчика значение 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();
Однако ничего не работает, count внутри компонента застрял на -1, хотя count установлено на 42. Мне просто кажется, что мой тест выполняется до завершения установки состояния?
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.info('count:', count);
this.setState({
count
});
}
componentDidUpdate() {
console.info('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>
)
}
}
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.info('text is:', text);
expect(text).toEqual('42 Notifications Awaiting!');
});
})



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Может быть, ваша describe также должна быть асинхронной функцией? await операторы должны быть объявлены внутри async области, не так ли?
Итак, я только что попробовал это, но получил это предупреждение> Возврат обещания из «описания» не поддерживается. Тесты должны быть определены синхронно. Возврат значения из «describe» не пройдет тест в будущей версии Jest.
Упс, я пропустил async в блоке it
Проблема заключалась в том, что await delay() не работал, чтобы все методы жизненного цикла React, такие как componentDidMount, создавали/вызывали.
Мне пришлось использовать Enzyme, хотя автор не рекомендовал его из-за большого количества открытых проблем с ошибками.
Используя Enzyme, я мог убедиться, что componentDidMount вызывается, и, таким образом, установить состояние count на 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.info('text is:', text);
expect(text).toEqual('42 Notifications Awaiting');
});
})
На самом деле, настоящая проблема была в файле isomorphic-react/src/components/__tests__/NotificationsViewer.js. delay импортированы неправильно, и это вызывало ошибку при тестировании.
При импорте delay вот так: import { delay } from 'redux-saga' устраните проблему. = Д
Это правильно, у меня был неправильный импорт. Однако я оставлю свой ответ ниже в качестве предпочтительного способа справиться с этим, поскольку не каждый проект будет использовать redux-saga, и мой пример объясняет, как использовать Enzyme для решения этой проблемы :)
Мне кажется, что
await delay()не позволяет запускать методы жизненного цикла до того, как будет протестирован блокexpect. Поскольку результатыconsole.info('text is:', text);обрабатываются первыми, затем обрабатываются журналыcomponentDidMountиcomponentDidUpdate.