是否可以测试使用注入而不使用包装组件的 Vue 3 组合库?

Posted

技术标签:

【中文标题】是否可以测试使用注入而不使用包装组件的 Vue 3 组合库?【英文标题】:Is it possible to test a Vue 3 Composition library which uses inject without a wrapping component? 【发布时间】:2021-10-12 06:34:19 【问题描述】:

我正在按照本指南创建身份验证组合库: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 属性,然后从 jest 中测试它,所以我纯粹是在测试 useSignup 代码?

【问题讨论】:

我目前的想法是更新useSignup函数以获取它将调用的authService,但我不禁觉得有更好的方法。 【参考方案1】:

在没有任何组件上下文的情况下测试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,
  ;

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

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

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

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

    验证模拟 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);
  )
)

【讨论】:

以上是关于是否可以测试使用注入而不使用包装组件的 Vue 3 组合库?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将 css 注入 Vue 组件样式部分?

在 Vue 3 Typescript 中使用提供/注入访问组件中的方法,错误对象可能是“未定义”

Vue 3 Composition API 提供/注入在单个文件组件中不起作用

测试包装的 vuetify 自动完成组件 v 菜单未在 html 中打开

我是不是需要(或应该)将我所有的 Vue 组件包装在一个包装器组件中?

将 react-intl 对象注入到已安装的 Enzyme 组件中进行测试