在Vitest中测试Vue组合式函数Watcher时,如何等待nextTick后断言?
解决Vue组合式函数Watcher单元测试的异步等待问题
针对你的场景,有两种优雅且贴合Vue/Vitest生态的方案可以替代setTimeout,确保断言在Watcher触发后执行:
方案1:使用Vue官方的nextTick
Vue的响应式更新、Watch回调都是异步执行的,会被推入微任务队列。nextTick是Vue提供的专门用于等待这些异步操作完成的API,语义清晰且精准。
修改后的测试代码:
import { nextTick } from 'vue'; test("check if onFooChange was called", async () => { const fooComposable = useFoo(); const spy = vi.spyOn(fooComposable, "onFooChange"); fooComposable.foo = "newData"; // 等待Vue的异步更新队列执行完毕,包括Watcher回调 await nextTick(); expect(spy).toHaveBeenCalledOnce(); });
方案2:使用Vitest的vi.runAllTicks()
vi.runAllTicks()会立即执行所有待处理的微任务,而Vue的nextTick内部正是基于微任务实现的,因此这个方法也能达到同样的效果,适合纯Vitest测试场景。
修改后的测试代码:
test("check if onFooChange was called", async () => { const fooComposable = useFoo(); const spy = vi.spyOn(fooComposable, "onFooChange"); fooComposable.foo = "newData"; // 执行所有微任务,触发Watcher回调 await vi.runAllTicks(); expect(spy).toHaveBeenCalledOnce(); });
为什么不推荐setTimeout?
setTimeout属于宏任务,会等到所有微任务(包括Vue的Watcher回调)执行完毕后才触发,虽然能生效,但它的执行时机比微任务晚,测试效率更低,且语义上不如上述两种方案清晰,不够贴合Vue的异步更新机制。
内容的提问来源于stack exchange,提问作者walox
相关产品推荐
相关产品推荐

