所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

前端测试驱动开发:Vitest 助力 Vue 项目单元测试工程化实战

单元测试前端开发的关键环节,它能确保代码按预期运行,并在投入生产之前预防错误。无论您是刚入门还是希望提升测试技能,本指南都能帮助您从前端单元测试的初学者晋升到高级水平

什么是单元测试?

简单来说,单元测试就是单独测试代码中的每一个小功能,看看它们是否正常工作。就像检查汽车的每个零件一样,确保每个部分都能正常运转。

为什么要进行单元测试?

  • 尽早发现错误 – 在开发阶段就能发现潜在问题
  • 提高代码质量 – 强制我们写出更好的代码结构
  • 使重构更安全 – 重构时有测试保障,不怕破坏现有功能
  • 记录预期行为 – 测试本身就是最好的文档

新手入门:写第一个测试

第一步:选择测试工具

流行的前端测试框架:

  • Jest(推荐用于 ReactVueJavaScript
  • Mocha + Chai(灵活但需要更多设置)
  • Vitest(快速,兼容 Vite

第二步:安装 Vitest

npm install --save-dev vitest

package.json 中添加测试脚本:

{
  "scripts": {
    "test": "vitest"
  }
}

第三步:写你的第一个测试

让我们测试一个简单的加法函数:

sum.js

export const sum = (a, b) => a + b;

sum.test.js

import { expect, test } from "vitest";
import { sum } from "./sum.js";

test("1加2应该等于3", () => {
  expect(sum(1, 2)).toBe(3);
});

运行测试:

npm test

恭喜!你刚刚编写了你的第一个单元测试!是不是比想像中简单?

进阶阶段:测试 Vue 组件

第一步:安装 Vue 测试工具

npm install --save-dev @vue/test-utils jsdom

vitest.config.js 配置

import { defineConfig } from "vitest/config";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [vue()],
  test: {
    environment: "jsdom",
    globals: true,
  },
});

第二步:测试 Vue 组件

Button.vue

<template>
  <button @click="onClick"><slot /></button>
</template>

<script setup>
const props = defineProps({ onClick: Function });
const onClick = () => props.onClick && props.onClick();
</script>

Button.test.js

import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils"; // 使用 Vue Test Utils 来挂载组件进行测试
import Button from "./Button.vue"; // 引入你的 Vue 组件

describe("Button.vue", () => {
  it("点击按钮时,应该触发 click 事件", () => {
    const wrapper = mount(Button); // 挂载组件
    wrapper.find("button").trigger("click"); // 触发按钮的点击事件
    expect(wrapper.emitted("click")).toBeTruthy(); // 检查是否触发了 click 事件
  });

  it("渲染插槽内容", () => {
    const wrapper = mount(Button, {
      slots: {
        default: "前端开发技术前沿",
      },
    });
    expect(wrapper.text()).toBe("前端开发技术前沿"); // 检查渲染的文本内容
  });
});

高级技巧:模拟和异步测试

模拟 API 调用

fetchData.js

export async function fetchData(url) {
  const response = await fetch(url);
  return response.json();
}

fetchData.test.js

import { vi, expect, test } from "vitest";
import { fetchData } from "./fetchData";

// 模拟 fetch 函数
global.fetch = vi.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ data: "前端开发技术前沿" }),
  })
);

test("fetchData 返回模拟数据", async () => {
  const data = await fetchData("https://code.ifrontend.net");
  expect(data).toEqual({ data: "前端开发技术前沿" });
  expect(fetch).toHaveBeenCalledWith("https://code.ifrontend.net");
});

测试组合式函数

useCounter.js

import { ref } from "vue";

export function useCounter(initialValue = 0) {
  const count = ref(initialValue);
  const increment = () => {
    count.value += 1;
  };
  return { count, increment };
}

useCounter.test.js

import { describe, it, expect } from "vitest";
import { defineComponent, h } from "vue";
import { mount } from "@vue/test-utils";
import { useCounter } from "./useCounter";

describe("useCounter", () => {
  it("increment 使计数加一", async () => {
    const TestComponent = defineComponent({
      setup() {
        const { count, increment } = useCounter(0);
        return { count, increment };
      },
      render() {
        return h("div", [
          h("span", this.count),
          h(
            "button",
            {
              onClick: this.increment,
            },
            "inc"
          ),
        ]);
      },
    });

    const wrapper = mount(TestComponent);
    await wrapper.find("button").trigger("click");
    expect(wrapper.find("span").text()).toBe("1");
  });
});

写好单元测试的秘诀

  • 测试功能,不测试实现 – 关注”做什么”,而不是”怎么做”
  • 一个测试只做一件事 – 每个测试只验证一个功能点
  • 起个好名字 – 测试名称要让人一看就知道在测什么
  • 隔离外部依赖 – 让测试不依赖网络、数据库等外部环境
  • 自动化运行 – 在代码提交时自动运行测试

写在最后

单元测试就像给代码买保险,虽然前期需要投入时间,但能让你在后续开发中更加安心。建议从简单的函数开始练习,慢慢扩展到组件测试。记住,好的测试不仅能帮你发现 bug,还能让你的代码质量更上一层楼!

原文链接:https://code.ifrontend.net/archives/1387,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?