Ответ 1
Вот фрагмент кода, который ожидает разрешения ожидающих выполнения обещаний:
const flushPromises = () => new Promise(setImmediate);
Я пишу интеграционный тест для приложения React, т.е. Тест, который тестирует многие компоненты вместе, и я хочу издеваться над любыми вызовами внешних служб.
Проблема заключается в том, что тест, похоже, выполняется до того, как выполняется асинхронный обратный вызов, что приведет к сбою моих тестов.
Во всяком случае, вокруг? Могу ли я как-то дождаться завершения вызова асинхронного кода?
Вот какой-то плохой псевдокод, чтобы проиллюстрировать мою точку зрения.
Я хотел бы проверить, что, когда я монтирую Parent, его дочерний компонент визуализирует содержимое, возвращаемое с внешней службы, которое я буду издеваться.
class Parent extends component
{
render ()
{
<div>
<Child />
</div>
}
}
class Child extends component
{
DoStuff()
{
aThingThatReturnsAPromise().then((result) => {
Store.Result = result
})
}
render()
{
DoStuff()
return(<div>{Store.Result}</div>)
}
}
function aThingThatReturnsAPromise()
{
return new Promise(resolve =>{
eternalService.doSomething(function callback(result) {
resolve(result)
}
}
}
Когда я это делаю в своем тесте, он терпит неудачу, потому что он запускается до того, как обратный вызов будет запущен.
jest.mock('eternalService', () => {
return jest.fn(() => {
return { doSomething: jest.fn((cb) => cb('fakeReturnValue');
});
});
describe('When rendering Parent', () => {
var parent;
beforeAll(() => {
parent = mount(<Parent />)
});
it('should display Child with response of the service', () => {
expect(parent.html()).toMatch('fakeReturnValue')
});
});
Как проверить это? Я понимаю, что угловой разрешает это с помощью zonejs, есть ли эквивалентный подход в React?
Вот фрагмент кода, который ожидает разрешения ожидающих выполнения обещаний:
const flushPromises = () => new Promise(setImmediate);
Я не знаю ничего родного для React, чтобы выполнить то, что вы ищете.
Однако, я смог выполнить это в аналогичном коде, вызвав beforeAll() @done после завершения установки. См. Изменения в коде ниже:
let setupComplete;
jest.mock('eternalService', () => {
return jest.fn(() => {
return { doSomething: jest.fn((cb) => { cb('fakeReturnValue'); setupComplete(); }) };
});
.
.
.
beforeAll(done => {
parent = mount(<Parent />)
setupComplete = done;
});
});
в то время как псевдокод может быть реорганизован, чтобы следовать жизненному циклу React (используя componentWillMount()
componentDidMount()
, было бы намного легче протестировать. Однако ниже мой непроверенный псевдокод относится к изменениям для ваших тестовых кодов, не стесняйтесь проверить его и обновите его. Надеюсь, это поможет вам!
describe('When rendering Parent', () => {
it('should display Child with the response of the service', function(done) => {
const parent = mount(<Parent />);
expect(parent.html()).toMatch('fakeReturnValue');
done();
});
});
Асинхронный характер JavaScript является основной причиной, по которой модульное тестирование JavaScript заняло столько времени, чтобы созреть. Jest предоставляет множество шаблонов для тестирования асинхронного кода, описанного здесь: http://jestjs.io/docs/en/asynchronous.html Я использую async/ожидание наиболее широко, так как это делает чрезвычайно читаемые тесты.
Но поскольку вы издеваетесь над асинхронным методом, нет необходимости в асинхронном коде. Увидеть ниже.
let parent
let eternalService = jest.fn(() => 'fakeReturnValue');
beforeEach(() => {
parent = mount(<Parent />)
parent.instance().externalService = externalService
})
describe('When rendering Parent', () => {
it('should display Child with response of the service', () => {
expect(parent.html()).toMatch('fakeReturnValue')
});
});
Я предлагаю вам экспортировать aThingThatReturnsAPromise()
из своего модуля или файла, а затем импортировать его в тестовый пример.
Поскольку aThingThatReturnsAPromise()
возвращает обещание, вы можете использовать асинхронные функции тестирования Jest. Жест будет ждать вашего обещания, и вы сможете сделать свои утверждения.
describe('When rendering Parent', () => {
var parent;
beforeAll(() => {
parent = mount(<Parent />)
});
it('should display Child with response of the service', () => {
expect.assertions(1);
return aThingThatReturnsAPromise().then( () => {
expect(parent.html()).toMatch('fakeReturnValue');
});
});
});
Для получения дополнительной информации прочитайте, как Jest обрабатывает тестовые примеры с помощью обещаний в Jest Docs здесь