2016-11-22 314 views
1

說我有一個組件,呈現一個簡單的div包含一個整數,從0開始,每秒鐘加1。因此,5秒後,組件應呈現「5」,30秒後呈現「30」等。如果我想測試這個組件,並確保它在5秒後渲染它,我可能會寫這樣的東西。如何在使用jest的模擬時間之後運行斷言測試?

it('should render <5> after 5 seconds',() => { 
    const time = mount(<Timer/>) 
    setTimeout(() => { 
    expect(time.text()).toEqual('5') 
    }, 5000) 
}) 

但是,這不起作用,因爲測試從未實際運行預期並且無論什麼都返回通過。即使它確實有效,使用這樣的超時也是非常低效的,因爲測試需要等待5秒鐘。而如果我想模擬更多的時間呢?在做了一些搜索之後,我發現笑話實際上有一個timer mock,但我似乎無法弄清楚如何在這種情況下實現它。任何幫助將不勝感激。謝謝!

+0

你能分享使用定時器的模塊代碼嗎? –

回答

0

您必須在`require'組件之前調用jest.useFakeTimers();才能模擬setTimeout。

這裏我們通過調用jest.useFakeTimers();來啓用假定時器。這 模擬出setTimeout和其他具有模擬功能的定時器功能。

而要測試異步工作流程Jest documentation says您必須爲每個'it'函數回調返回一個Promise

要測試異步函數,只需從中返回一個承諾即可。當 正在運行測試時,Jest將等待 讓測試完成之前解決的承諾。您也可以在beforeEach,afterEach,beforeAll或afterAll函數之後返回 的承諾。例如, 假設fetchBeverageList()返回一個承諾,該承諾應該是 解析爲列表中含有檸檬的列表。


所以,你可以寫類似:您可以測試這個

it('should render <5> after 5 seconds',() => { 
    jest.useFakeTimers(); 
    //only after that, require your componenet 
    let Timer = require('./timer'); 
    const time = mount(<Timer/>); 
    jest.runAllTimers(); 
    expect(setTimeout.mock.calls.length).toBe(1); 
    expect(setTimeout.mock.calls[0][1]).toBe(5000); 
    expect(time.text()).toEqual('5'); 
}) 
+0

謝謝。雖然我仍然不確定當異步函數是期望調用本身時,承諾應該如何看待。 – JakeP

+0

你不需要,因爲如果你模擬settimeout,你的測試將會同步運行。我寫了兩個答案,因爲你提出了兩個問題:) – Cleiton

+0

再次感謝!我試過這個,但是我得到了錯誤「Ran 100000定時器,還有更多!假設我們已經達到了無限遞歸和救助......」也許這是因爲Timer組件的間隔每1000毫秒運行一次? – JakeP

1

爲了玩笑知道你的測試是異步,你需要:1)返回無極,或2)在測試回調申報的參數,如下所示:

it('should render <5> after 5 seconds', done => { 
    // test stuff 
}); 

源:https://facebook.github.io/jest/docs/en/asynchronous.html

爲了讓你的測試工作:

it('should render <5> after 5 seconds', done => { 
    jest.useFakeTimers(); // this must be called before any async things happen 

    const time = mount(<Timer/>); 

    setTimeout(() => { 
    // Note the placement of this try/catch is important. 
    // You'd think it could be placed most anywhere, but nope... 
    try { 
     // If this assertion fails, an err is thrown. 
     // If we do not catch()...done.fail(e) it, 
     // then this test will take jasmine.DEFAULT_TIMEOUT_INTERVAL (5s unless you override) 
     // and then fail with an unhelpful message. 
     expect(time.text()).toEqual('5'); 
     done(); 
    } catch(e) { 
     done.fail(e); 
    } 
    }, 5000); 
    jest.runTimersToTime(5000); // This basically fast forwards 5s. 
}); 
+0

這些try/catch編寫起來很麻煩,所以我做了一些我希望儘快發佈的測試utils。除了許多其他的東西,它可以縮短setTimeout()的回調體到: 'tf.finish(done,()=> expect(time.text())。toEqual('3'));' 如果您有興趣,請告訴我,我會努力讓您發佈! –

相關問題