【问题标题】:Jest react testing: Check state after delay开玩笑反应测试:延迟后检查状态
【发布时间】:2018-01-10 17:38:51
【问题描述】:

在 Jest 文档 https://facebook.github.io/jest/docs/timer-mocks.html#content 的帮助下创建测试时我真的很困惑

我正在尝试检查容器装载时的状态,然后在几秒钟后,在我手动设置状态中的值之后(使用 setTimeout())。

我在 Main 的 componentDidMount 中有一个函数,如下所示:

componentDidMount() {
    this.setStateAfterDelay();
}

而函数的作用是:

setStateAfterDelay = () => {
    setTimeout(() => {
        this.setState({ fruits: ['banana', 'apple', 'orange', 'vodka', 'kiwi'] });
    }, 1500);
}

我完成了第一部分:

const component = mount(<Main />);
expect(component.state().fruits).toEqual(null);

但我不知道如何在 2000 毫秒后再次检查状态?

任何帮助表示赞赏:)

【问题讨论】:

    标签: javascript reactjs unit-testing jestjs


    【解决方案1】:

    虽然 jest 可以轻松运行异步代码,但您可以使用 promise 和 setTimeout 组合来稍等片刻。例如此代码将等待 2 秒:

    await new Promise((r) => setTimeout(r, 2000));
    

    完整的样本测试。别忘了在回调函数前加上async标志:

    test('some test title', async () => {
      const foo = true;
      await new Promise((r) => setTimeout(r, 2000));
      expect(foo).toBeDefined();
    });
    

    另外,请记住,默认的“超时”为 5 秒(5000 毫秒)。如果您的测试可能运行更长时间,您可以在test() 上方添加jest.setTimeout(30000);。 30000 将确保不会超时 30 秒。您可以添加任何您需要的号码。 setTimeout 的完整示例:

    jest.setTimeout(30000);
    
    test('some test title', async () => {
      const foo = true;
      await new Promise((r) => setTimeout(r, 2000));
      expect(foo).toBeDefined();
    });
    

    【讨论】:

    • 与 FakeTimers 有什么区别?
    • FakeTimers,顾名思义,是假计时器。 setTimeout 将等待真正的秒数。在此处阅读文档:jestjs.io/docs/timer-mocks
    【解决方案2】:

    我还没有真正测试过这段代码。但是,我认为类似的事情应该可以工作。

    const fruits = ['banana', 'apple', 'orange', 'vodka', 'kiwi'];
    
    it('mock setTimeout test', () => {
     jest.useFakeTimers();
     setTimeout(() => {
       expect(component.state().fruits).toEqual(fruits);
     }, 1500);
     jest.runAllTimers();
    });
    

    【讨论】:

    • 是的,这似乎很好用!我认为单元测试有一些疯狂的语法来实现这一点。谢谢!
    • 这个期望真的会运行吗?我没有看到调试指针点击这里,但我的测试用例变绿了。
    • 这似乎不起作用。你在哪里安装?
    【解决方案3】:

    您无需延迟测试,只需在断言之前调用jest.runAllTimers() 即可。

    const fruits = ['banana', 'apple', 'orange', 'vodka', 'kiwi'];
    
    it('initializes the fruits state', () => {
     jest.useFakeTimers();
     jest.runAllTimers();
     expect(component.state().fruits).toEqual(fruits);
    });
    

    如果您要进行多次测试,您也可以在beforeEach 中调用useFakeTimers(),并且runAllTimers() 可以在另一个beforeEach 中,因此您不要重复自己。

    【讨论】:

      【解决方案4】:

      我知道这是关于如何在 20 秒后检查某事的问题。但这也可能表明您不想测试 20 秒,因为有时重要的是是否已使用正确的输入执行了某些操作。在这种情况下,您可以稍微重构您的代码,以便您可以传入一个调度函数。比如

          function abc() {
              return dispatch => {
                  return Promise.then(res => {})  // this would take 20 seconds
              }
          }
      

      因为传入了dispatch,所以可以很方便的在测试代码中使用下面的代码。

          const dispatch = Jest.fn()
          abc(dispatch)
          expect(dispatch).toBeCalled()
      

      当然,假设是您不关心是否是 20 秒,而是您更关心工作流程。

      【讨论】:

        猜你喜欢
        • 2017-01-25
        • 2020-03-02
        • 2015-10-27
        • 2021-05-09
        • 2021-06-05
        • 1970-01-01
        • 2022-08-07
        • 2018-07-22
        • 2019-11-22
        相关资源
        最近更新 更多