You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Directus SDK与Vitest的函数测试方法求助

解决Directus SDK单元测试的Mock问题

第一步:修复空Token测试的前置问题

你第三个测试的核心问题是调用directusSDK("")会直接抛出URL错误,根本无法获取SDK实例去调用getQuestions。测试空Token场景时,必须先传入合法的URL(随便填一个有效格式的字符串即可,比如"http://mock-directus"),才能继续验证getQuestions的逻辑:

describe("given no token was provided", () => {
  test("an error is thrown", async () => {
    const sdk = directusSDK("http://mock-directus");
    // 注意getQuestions是异步函数,要用rejects断言异步错误
    await expect(sdk.getQuestions("")).rejects.toThrowError("token was faulty!");
  });
});

第二步:Mock Directus SDK,避免真实请求

单元测试不需要连接真实的Directus服务器,直接Mock SDK的核心方法即可,比用MSW更简单高效。

1. Mock整个Directus SDK模块

在测试文件顶部添加Mock逻辑,模拟SDK的链式调用和返回值:

import { vi } from "vitest";

// Mock @directus/sdk的所有导出
vi.mock("@directus/sdk", () => {
  // 模拟request方法的成功返回
  const mockRequest = vi.fn().mockResolvedValue([
    { id: 1, question: "测试问题1" },
    { id: 2, question: "测试问题2" }
  ]);

  const mockClient = {
    request: mockRequest,
    with: vi.fn().mockReturnThis() // 链式调用返回自身,模拟.with()的行为
  };

  return {
    createDirectus: vi.fn().mockReturnValue(mockClient),
    authentication: vi.fn(),
    rest: vi.fn(),
    withToken: vi.fn().mockReturnArg(1), // 返回传入的第二个参数,即readItems的配置
    readItems: vi.fn()
  };
});

2. 测试getQuestions的正常流程

验证当URL和Token都有效时,函数能正确调用SDK并返回数据:

describe("given valid url and token", () => {
  test("returns questions data", async () => {
    const sdk = directusSDK("http://mock-directus");
    const result = await sdk.getQuestions("valid-token");
    
    expect(result).toEqual([
      { id: 1, question: "测试问题1" },
      { id: 2, question: "测试问题2" }
    ]);
    // 验证request方法被正确调用
    const { createDirectus } = await import("@directus/sdk");
    const mockClient = createDirectus.mock.results[0].value;
    expect(mockClient.request).toHaveBeenCalled();
  });
});

3. 测试请求失败的场景

模拟Directus返回错误的情况,验证函数的错误处理逻辑:

test("handles request error gracefully", async () => {
  const { createDirectus } = await import("@directus/sdk");
  const mockClient = createDirectus.mock.results[0].value;
  // 模拟请求失败
  mockClient.request.mockRejectedValue(new Error("Directus server error"));

  const sdk = directusSDK("http://mock-directus");
  const result = await sdk.getQuestions("valid-token");
  
  // 因为函数内部catch了错误,所以返回undefined
  expect(result).toBeUndefined();
  // 验证错误被打印(可选)
  const consoleSpy = vi.spyOn(console, "error").mockImplementation();
  await sdk.getQuestions("valid-token");
  expect(consoleSpy).toHaveBeenCalledWith(new Error("Directus server error"));
  consoleSpy.mockRestore();
});

补充:完善你的main.ts代码

注意你的directusSDK函数没有返回getQuestions方法,外部无法调用,必须补充返回逻辑:

function directusSDK(directusURL: string) {
  if (!directusURL) throw Error("url was faulty!");

  const client = createDirectus(directusURL).with(authentication()).with(rest());

  async function getQuestions(token: string) {
    try {
      if (!token) throw Error("token was faulty!");
      const result = await client.request<Questions[]>(
        withToken(token, readItems('Questions', { fields: ['*'] }))
      );
      return result;
    } catch (error: any) {
      console.error(error);
    }
  }

  // 暴露getQuestions方法
  return { getQuestions };
}

// 定义Questions类型
type Questions = {
  id: number;
  question: string;
  // 补充你的其他字段
};

内容的提问来源于stack exchange,提问作者angularNoob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:38:28