所以我们需要在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赋值
内容版权声明:除非注明,否则皆为本站原创文章。