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

2020-06-14 06:26:38易采站长站整理

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

测试结果发现,addCounter被触发时handler方法并没有执行

因为lodash中debounce方法涉及到了setTimeout,`hanlder方法应该是在500ms后执行,所以在此时执行时方法没有执行。

所以我们需要在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))
}));