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 次