2017-01-22 7 views
3

Я пытаюсь написать тест для компонента React, который должен завершить асинхронное действие в своем методе componentWillMount. componentWillMount вызывает функцию, переданную в качестве опоры, которая возвращает обещание, и я издеваюсь над этой функцией в своем тесте.Jest: тесты не могут терпеть неудачу в пределах setImmediate или process.nextTick callback

Это нормально работает, но если тест не выполняется при вызове setImmediate или process.nextTick, исключение не обрабатывается Jest, и оно выходит преждевременно. Ниже вы можете видеть, что я даже пытаюсь поймать это исключение, но безуспешно.

Как я могу использовать что-то вроде setImmediate или nextTick с Jest? Принятый ответ на этот вопрос - это то, что я пытаюсь реализовать безуспешно: React Enzyme - Test `componentDidMount` Async Call.

it('should render with container class after getting payload', (done) => { 
    let resolveGetPayload; 
    let getPayload = function() { 
    return new Promise(function (resolve, reject) { 
     resolveGetPayload = resolve; 
    }); 
    } 
    const enzymeWrapper = mount(<MyComponent getPayload={getPayload} />); 

    resolveGetPayload({ 
    fullname: 'Alex Paterson' 
    }); 

    try { 
    // setImmediate(() => { 
    process.nextTick(() => { 
     expect(enzymeWrapper.hasClass('container')).not.toBe(true); // Should and does fail 
     done(); 
    }); 
    } catch (e) { 
    console.log(e); // Never makes it here 
    done(e); 
    } 
}); 

Jest v18.1.0

Узел v6.9.1

+0

вы читали документацию о тестировании асинхронном материала (http://facebook.github.io /jest/docs/tutorial-async.html#content)? –

+0

Да, я не тестирую асинхронную функцию, я тестирую компонент, который должен ждать обещания. –

+0

Но вы создаете обещание, и даже вы разрешаете его в тесте, он не будет иметь никакого эффекта в тестовом прогоне, вам нужно хотя бы вернуть обещание от теста. –

ответ

0

Некоторые вещи, чтобы отметить;

  • process.nextTickявляется асинхронной, поэтому попытка/выгода не будет в состоянии захватить это.
  • Promise также будет разрешать/отклонять асинхронный режим, даже если код, выполняемый в Promise, является синхронизацией.

Дайте это попробовать

it('should render with container class after getting payload', (done) => { 
    const getPayload = Promise.resolve({ 
     fullname: 'Alex Paterson' 
    }); 
    const enzymeWrapper = mount(<MyComponent getPayload={getPayload} />); 

    process.nextTick(() => { 
     try { 
      expect(enzymeWrapper.hasClass('container')).not.toBe(true); 
     } catch (e) { 
      return done(e); 
     } 
     done(); 
    }); 
}); 
+0

Не должно быть 'return fail (e)' вместо 'return done (e);'? –

+0

нет Насколько мне известно, метод 'fail', только« done »callback: https://facebook.github.io/jest/docs/en/asynchronous.html#callbacks –

1

Преодолеть эту проблему следующим способом атм (также решает проблему с ферментного и асинхронном вызове в componentDidMount и асинхронном SetState):

it('should render proper number of messages based on itemsPerPortion', (done) => { 
    const component = shallow(<PublishedMessages itemsPerPortion={2} messagesStore={mockMessagesStore()} />); 

    setImmediate(() => { // <-- that solves async setState in componentDidMount 
    component.update(); 

    try { // <-- that solves Jest crash 
     expect(component.find('.item').length).toBe(2); 
    } catch (e) { 
     return fail(e); 
    } 

    done(); 
    }); 
}); 

(Фермент 3.2.0, Jest 21.1.6)

ОБНОВЛЕНИЕ

Просто понял, другой, лучше (но все-таки странно) решение о том, используя асинхронном/ОЖИДАНИЕ (и до сих пор решения асинхронной componentDidMount и асинхронной SetState):

it('should render proper number of messages based on itemsPerPortion', async() => { 
    // Magic below is in "await", looks as that allows componentDidMount and async setState to complete 
    const component = await shallow(<PublishedMessages itemsPerPortion={2} messagesStore={mockMessagesStore()} />); 

    component.update(); // still needed 
    expect(component.find('.item').length).toBe(2); 
}); 

также другие асинхронному связанные действия должны начинаться с префикса await а как

await component.find('.spec-more-btn').simulate('click'); 
0

- Проводка в качестве ответа на один не может форматировать блоки кода в комментариях. -

Опираясь на ответ Владимира, обратите внимание, что использование асинхр/ждут работы в beforeEach, а также:

var wrapper 

beforeEach(async() => { 
    // Let's say Foobar's componentDidMount triggers async API call(s) 
    // resolved in a single Promise (use Promise.all for multiple calls). 
    wrapper = await shallow(<Foobar />) 
}) 

it('does something',() => { 
    // no need to use an async test anymore! 
    expect(wrapper.state().asynchronouslyLoadedData).toEqual(…) 
}) 

 Смежные вопросы

  • Нет связанных вопросов^_^