开玩笑反应测试:延迟后检查状态

Posted

技术标签:

【中文标题】开玩笑反应测试:延迟后检查状态【英文标题】: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 毫秒后再次检查状态?

任何帮助表示赞赏:)

【问题讨论】:

【参考方案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 秒,而是您更关心工作流程。

【讨论】:

以上是关于开玩笑反应测试:延迟后检查状态的主要内容,如果未能解决你的问题,请参考以下文章

流星反应开玩笑测试

调用 React Setstate 回调但延迟渲染

开玩笑 - 如何测试组件是不是不存在?

idea上Run,Debug为灰色,执行main方法,单元测试rundebug点击后均没反应,像假死状态的解决方法

多个复选框过滤反应状态

用开玩笑酶测试反应路由器 v4