如果您使用“vi.mock”工厂,请确保内部没有顶级变量

问题描述 投票:0回答:1

我是测试新手,想了解如何使用

mysql2
Kysely
数据库模拟为
vitest
的实例。我一直在关注 GitHub 提供的线程,但遇到了标题所示的错误:

数据库.ts

import * as dotenv              from "dotenv";
import { type DB }              from "../types/schema.types";
import { createPool, }          from "mysql2";
import { Kysely, MysqlDialect } from "kysely";
dotenv.config();

export const dialect = new MysqlDialect({
  pool: createPool({
    database: `${process.env.DATABASE}`,
    host: `${process.env.DATABASE_HOST}`,
    port: process.env.DATABASE_PORT as unknown as number,
    user: `${process.env.USER}`,
    password: process.env.PASSWORD,
    waitForConnections: true,
    multipleStatements: true,
    charset: "utf8mb4",
    connectionLimit: `${process.env.DATABASE_CONNECTION_LIMIT}` as unknown as number,
    queueLimit: 0,
  }),
})

const db = new Kysely<DB>({ dialect });
export default db;

样品.规格.ts

import { it, vi, expect } from "vitest";
import db from "../database/database";
import { DB } from "../types/schema.types";
import { Kysely, MysqlDialect } from "kysely";

// Test case
it("Get user count", async () => {
  const mocks = vi.hoisted(() => ({ query: vi.fn() }));
  
  // Mocking database module
  vi.mock("../database/database", async (importOriginal) => {
    const actualModule = await importOriginal<typeof import("../database/database")>();
    return {
      ...actualModule,
      __esModule: true,
      ownerDb: new Kysely<DB>({
        dialect: new MysqlDialect({ pool: vi.fn() }),
      }),
    };
  });

  mocks.query.mockResolvedValue({ rows: [{ count: 1 }] });

  const query = db
    .selectFrom("users")
    .select((eb) => eb.fn.count<number>("users.user_id").as("count"));

  const { count } = await db
    .selectNoFrom((eb) => eb.fn.coalesce(query, eb.lit(0)).as("count"))
    .executeTakeFirstOrThrow();

  expect(count).toBe(1);
node.js unit-testing mysql2 vitest kysely
1个回答
0
投票

来自 vi.mock 文档...

vi.mock 被提升(换句话说,移动)到文件顶部。这意味着无论您何时编写它(无论是在 beforeEach 内部还是测试内部),它实际上都会在此之前被调用。

这意味着真正运行的是这样的:

import { it, vi, expect } from "vitest";

// Mocking database module
vi.mock("../database/database", async (importOriginal) => {
  const actualModule = await importOriginal<typeof import("../database/database")>();
  return {
    ...actualModule,
    __esModule: true,
    ownerDb: new Kysely<DB>({
      dialect: new MysqlDialect({ pool: vi.fn() }),
    }),
  };
});

import db from "../database/database";
import { DB } from "../types/schema.types";
import { Kysely, MysqlDialect } from "kysely";

// Test case
it("Get user count", async () => {
  const mocks = vi.hoisted(() => ({ query: vi.fn() }));

传递给

vi.mock
的块看不到
DB
。您可以在导入时使用
vi.hoisted
。然后导入将与对
vi.mock
的调用一起提升。

import { it, vi, expect } from "vitest";
import db from "../database/database";
import { Kysely, MysqlDialect } from "kysely";
const { DB } = vi.hoisted(() => await import('../types/schema.types'));

请参阅使用 Vitest 模拟 Svelte Stores 的实用指南


但是,提升使得代码非常难以理解,并且

vi.mock
充满了警告。考虑使用
vi.doMock
代替。请注意,您必须动态导入 ../database/database。

© www.soinside.com 2019 - 2024. All rights reserved.