详解Jest结合Vue-test-utils使用的初步实践(12)

所以我们需要在Jest中对setTimeout进行特殊的处理:Jest提供了相关的方法,我们需要使用的是jest.useFakeTimers()和jest.runAllTimers()

前者是用来让Jest模拟我们用到的诸如setTimeout、setInterval等计时器,而后者是执行setTimeout、setInterval等异步任务中的宏任务(macro-task)并且将需要的新的macro-task放入队列中并执行,更多信息的可以参考官网的timer-mocks。

所以对test6.spec.js进行修改,在代码开始增加jest.useFakeTimers(),在触发addCounter方法后通过jest.runAllTimers()触发macor-task任务

jest.useFakeTimers();

import { shallow } from 'vue-test-utils';
import Test6 from '@/components/Test6';
import _ from 'lodash';

describe('Test for Test6 Component', () => {
 let wrapper;

 beforeEach(() => {
  wrapper = shallow(Test6);
 });

 afterEach(() => {
  wrapper.destroy()
 });

 it('test for lodash', () => {
  const mockFn2 = jest.fn();
  wrapper.setMethods({ handler: mockFn2 });
  wrapper.vm.addCounter();

  jest.runAllTimers();

  expect(mockFn2).toHaveBeenCalledTimes(1);
 })
});

结果还是失败,报错原因是:

Ran 100000 timers, and there are still more! Assuming we've hit an infinite recursion and bailing out…

程序陷入了死循环,换用Jest提供额另外一个API:jest.runOnlyPendingTimers(),这个方法只会执行当前队列中的macro-task,遇到的新的macro-task则不会被执行

将jest.runAllTimers()替换为jest.runOnlyPendingTimers()后,上面的错误消失了,但是handler仍然没有被执行

在查了许多资料后,这可能是lodash的debounce机制与jest的timer-mocks 无法兼容,如果有人能够解决这个问题希望能够指教。

这样的情况下,我们退而求其次,我们不去验证addCounter是否会被debounce,因为debounce是第三方模块的方法,我们默认认为是正确的,我们要验证的是addCounter能够正确触发handler方法即可。

所以我们可以另辟蹊径,通过mock将lodash的debounce修改为立即执行的函数,我们要做的是为lodash的debounce替换为jest.fn(),并且提供一个工厂函数,返回值就是传入的函数

import _ from 'lodash';

jest.mock('lodash', () => ({
 debounce: jest.fn((fn => fn))
}));

在如此修改后,测试通过,handler方法正确执行

同一个方法的多次mock

在一个组件中,我们可能会多次用到同一个外部的方法,但是每次返回值是不同的,我们可能要对它进行多次不同的mock

举个例子,在组件Test7中,mounted的时候forData返回一个数组,经过map处理后赋给text,点击getResult按钮,返回一个0或1的数字,根据返回值为result赋值

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/223.html