2016-11-22 304 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'));' 如果您有兴趣,请告诉我,我会努力让您发布! –

相关问题