Vue 3 组合式函数测试:用 Vitest 给 composable 写单元测试
test12026-10-222 次阅读
为什么测 composable
组合式函数把可复用的状态与副作用从组件里抽出来,它本身有逻辑、有生命周期、有异步。把它当纯函数测,能在界面还没写出来之前就锁定行为,比等到组件集成后再调要便宜得多。
测同步 composable:用 nextTick 推演响应式
Vue 的响应式是异步派发的,断言前要 await nextTick,否则读到的还是旧值。下面给一个 useCounter 写用例,覆盖自增与重置。
import { describe, it, expect } from "vitest";
import { ref } from "vue";
import { nextTick } from "vue";
function useCounter(initial = 0) {
const count = ref(initial);
const inc = () => { count.value++; };
const reset = () => { count.value = initial; };
return { count, inc, reset };
}
describe("useCounter", () => {
it("inc 后 count 自增并能被读到", async () => {
const { count, inc } = useCounter(1);
inc();
await nextTick();
expect(count.value).toBe(2);
});
it("reset 回到初始值", async () => {
const { count, inc, reset } = useCounter(0);
inc(); inc();
reset();
await nextTick();
expect(count.value).toBe(0);
});
});测异步 composable:用 fake timers 控制时间
带防抖或定时器的 composable 可以配合 vi.useFakeTimers 推进时钟,断言副作用在正确时机触发。
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { ref, watch } from "vue";
import { nextTick } from "vue";
function useDebounced(src: ReturnType<typeof ref>, delay = 300) {
const out = ref(src.value);
let t: ReturnType<typeof setTimeout>;
watch(src, (v) => {
clearTimeout(t);
t = setTimeout(() => { out.value = v; }, delay);
});
return out;
}
describe("useDebounced", () => {
beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());
it("300ms 内不更新,到点才生效", async () => {
const src = ref("a");
const out = useDebounced(src);
src.value = "b";
await nextTick();
expect(out.value).toBe("a");
vi.advanceTimersByTime(300);
await nextTick();
expect(out.value).toBe("b");
});
});关键结论
- 断言响应式结果前一定 await nextTick。
- 时间相关的 composable 用 fake timers 把不可控变成可断言。
- 组合式函数测试不依赖 DOM,跑得比组件测试快一个量级。
T
test1
文章作者
为什么测 composable 组合式函数把可复用的状态与副作用从组件里抽出来,它本身有逻辑、有生命周期、有异步。把它当...
- 分类
- 技术
- 发布时间
- 2026-10-22
- 字数
- 约 1884 字
- 阅读
- 2 次
