是否可以测试使用不带包装组件的 inject 的 Vue 3 Composition 库?

Is it possible to test a Vue 3 Composition library which uses inject without a wrapping component?

我正在按照本指南创建身份验证组合库:https://mattlaw.dev/blog/vuejs-the-composition-api-and-firebase-authentication/

在高层次上,您定义了一个文件 /src/components/auth/index.ts 并且该文件定义了 refs 和“使用”函数并直接导出,例如:

export const user = ref(null);

export function useSignup() {
  const email = ref("");
  const password = ref("");

  async function signup() {
    if (email.value == "" || password.value == "") return;

    const creds = await auth.createUserWithEmailAndPassword(
      email.value,
      password.value
    );

    if (!creds.user) throw Error("Signup failed");

    user.value = creds.user;
  }

  return {
    email,
    password,
    signup,
  };
}

我想用注入的虚假身份验证服务替换“auth.createUserWithEmailAndPassword”,这样我就可以纯粹测试 useSignup 函数,但我不想启动一个完整的组件来将其包装为一部分我的测试。有没有办法获取 vue 应用程序上下文,“提供”一个 DI 属性,然后从玩笑中测试它,所以我纯粹是在测试 useSignup 代码?

在没有任何组件上下文的情况下测试 useSignup() 的一种方法是在 useSignup() 中导入 auth 模块:

import { ref } from "vue";
import auth from "@/auth"; // 

export const user = ref(null);

export function useSignup() {
  const email = ref("");
  const password = ref("");

  async function signup() {
    if (email.value == "" || password.value == "") return;

    const creds = await auth.createUserWithEmailAndPassword(
      email.value,
      password.value
    );

    if (!creds.user) throw Error("Signup failed");

    user.value = creds.user;

    return creds.user
  }

  return {
    email,
    password,
    signup,
  };
}

然后您的测试可以模拟该模块:

  1. 在测试文件的顶部使用jest.mock('@/auth')

  2. 在您的测试中,require 模块(已在上面模拟),并使用 mockReturnValue() 设置模拟 return 值。

  3. 设置凭据 ref 值,然后调用 signup().

  4. 验证调用了模拟 createUserWithEmailAndPassword()

import { useSignup } from "@/useSignup";

jest.mock("@/auth"); 1️⃣

describe("useSignup", () => {
  it("signs in", async () => {
    2️⃣
    const { createUserWithEmailAndPassword } = require("@/auth").default;
    const myEmail = "john@gmail.com";
    createUserWithEmailAndPassword.mockReturnValue({
      user: myEmail
    });

    3️⃣
    const { email, password, signup } = useSignup();
    email.value = myEmail;
    password.value = "myPassword";
    await signup();

    4️⃣
    expect(createUserWithEmailAndPassword).toHaveBeenCalledWith(email.value, password.value);
  })
})