2017-01-22 38 views
3

我正在嘗試爲需要在其componentWillMount方法中完成異步操作的React組件編寫測試。 componentWillMount調用一個函數,作爲道具傳遞,返回一個承諾,並在我的測試中嘲笑這個函數。Jest:測試無法在setImmediate或process.nextTick回調中失敗

這工作正常,但如果測試在setImmediateprocess.nextTick的調用中失敗,該異常不由Jest處理並且它過早退出。下面,你可以看到我甚至試圖捕捉這個異常,但無濟於事。

我該如何使用setImmediatenextTick與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); 
    } 
}); 

玩笑v18.1.0

節點v6.9.1

+0

有你閱讀測試異步東西的文檔(http://facebook.github.io /jest/docs/tutorial-async.html#content)? –

+0

是的,我沒有測試一個異步函數,我正在測試一個需要等待承諾的組件。 –

+0

但是你創造了一個承諾,即使你在測試中解決它,它在測試運行中也沒有任何影響,你至少需要從測試中返回承諾。 –

回答

0

需要注意以下幾點;

  • process.nextTick異步的,所以的try/catch將無法捕捉。
  • 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

不存在''失敗'方法據我所知,只有'done'回調:https://facebook.github.io/jest/docs/en/asynchronous.html#callbacks –

1

克服這一問題,ATM接下來的方式(也解決了這個問題,在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(); 
    }); 
}); 

(Enzyme 3.2.0,Jest 21.1.6)

UPDATE

只是想出了另一個更好的(但仍怪)上使用異步解決方案/伺機(它仍然解決異步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(…) 
}) 
相關問題