96SEO 2026-08-08 19:52 2
src/
stores/
mailStore.ts
mailStore.test.ts ← 新增:Store 单元测试。条用例
components/
MailItem.vue
MailItem.test.ts ← 新增:组件测试,条用例
MailSearch.vue
MailSearch.test.ts ← 新增:组件测试,条用例
MailList.vue
MailList.test.ts ← 新增:组件测试,条用例
vite.config.ts ← 修改:新增 test/coverage 配置
package.json ← 修改:新增 test、test:coverage 脚本
全周一共 条测试用例,整体语句覆盖率 %。话说回来,

手动验证“点点点”成本高且易漏检。
单元测能把验证过程写成代码。一条命令即可跑完全部,用例能精准指出失败位置。
pnpm add -D vitest @vue/test-utils jsdom
vitest : 测试框架本体;跑用例、断言、覆盖率统计。@vue/test-utils : Vue 官方工具,挂载组件、模拟交互、检查渲染结果。jsdom : 在 Node 环境里模拟浏览器 DOM,让 document/window 可用。
主要痛点是缺少真实浏览器时需要 jsdom 模拟,否则 @vue/test-utils/mount 无法正常工作。
vite.config.ts 里加配置:
// vite.config.ts
///
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins:,test: {
environment: 'jsdom',// 用 jsdom 模拟浏览器环境
globals: true,// 全局注入 describe/it/expect
}。})
package.json 加脚本:
{
"scripts":{
"test"这方面,"vitest"
}
}
// 三件套示例
describe => {
it => {
expect.toBe // assert 判断结果是否正确
})
})
// describe 可以嵌套,用来分层组织大项目的不同模块。其实,**痛点**这方面。
-
"断言方式"混乱导致误判。"
.
-
"未使用 beforeEach 重置 Pinia" 导致不同用例互相污染。"
.
-
"异步操作未 await" 导致假通过但实际无效。"
.
`}
`
常见断言方法区别——toBe vs toEqual——关键痛点:
expect.toEqual // 深度比较适合数组/对象
expect.toBeNull // 专门判断 null
expect).toBeUndefined // undefined 专属
// toBe 使用 === 全等比较。引用不一致会失败
expect.toBe // ❌ fail
expect.toEqual // ✅ pass
// 因为每次创建 都是新引用,要使用 toEqual 而非 toBe。**痛点**这方面,
-
"错误地使用了 toBe" 把一样内容却不同引用的数据判定为不等。"."
.
`}
`
beforeEach 与 Pinia 实例隔离——避免数据泄漏痛点:
describe => {
beforeEach => { setActivePinia) }) // 每个 useMailStore 都会得到新实例
})
如果不做重置。第一个用例修改了 `mails` 后第二个会看到旧数据,从而导致假通过或假失败。
异步 + await 必须——防止假通过隐患:
it => {
const store = useMailStore
await store.fetchMails // 必须 await 完整执行
expect.toBe
})
没有 `async/await` 的话。在 `fetchMails` 的 Promise 未 resolve 前就完成断言,从而得到绿灯却并未真正验证。
新增文件 src/stores/mailStore.test.ts :示例代码与常见问题汇总:
import { describe,it,expect,beforeEach } from 'vitest'
import { setActivePinia。createPinia } from 'pinia'
import { useMailStore } from './mailStore'
describe => {
beforeEach => { setActivePinia) })
it => {
const store = useMailStore
expect.toEqual
expect.toBe
})
it => {
const store = useMailStore
const fetchPromise = store.fetchMails
expect.toBe
await fetchPromise
expect.toBe
expect.toBe
expect.toBe
})
it => {
const store = useMailStore
await store.fetchMails
const firstMail = store.mails
store.markAsRead
expect.toBe
})
/* 更多业务逻辑断言…*/
})
至于Day2,组件测试
为什么需要 @vue/test-utils?说到—痛点直击,
`mailStore.test.ts` 测的是纯逻辑,不涉及 DOM。但 ` ` 与 ` ` 等组件,需要验证渲染结果与交互事件 —— 所以必须把它们挂载成真实 DOM 并触发事件。若没有 `@vue/test-utils/mount` 就无法完成这一步。
新增文件 src/components/MailItem.test.ts :主要代码与典型踩坑汇总:
import { describe,it,expect } from 'vitest'
import { mount } from '@vue/test-utils'
import { ref } from 'vue'
import MailItem from './MailItem.vue'
import { meModeKry } from '@/types/injectionKeys'
describe => {
const baseProps = {
再看id。'',subject: '周一例会通知',from: '',isRead: false,createdAt: new Date
}
it => {
const wrapper = mount
expect).toContain
expect).toContain
})
it => {
const wrapper = mount
const li = wrapper.find
expect).toContain
})
/* 更多场景…
*/
})
痛点评价
技巧
痛点
对策
mount
没有真实 DOM → 无法触发事件
jsdom 提供模拟
text vs find
验证文本足够。但无法检测样式或事件
用 find 获取元素再读取属性
trigger + await
点击后 Vue 更新是异步
必须 await wrapper.find.trigger
global.provide / inject
没有父组件时 inject 默认值失效
在 mount 时通过 global.provide 注入 mock 值
jsdom 转换颜色
十六进制颜色被转换为 rgb 格式
用 rgb 或者直接匹配类名 / snapshot
ts
import { describe,it,expect } from 'vitest'
import { mount } from '@vue/test-utils'
import MailSearch from './MailSearch.vue'
describe => {
it=>{ /* ... */ })
it=>{ /* ... */ })
it=>{ /* ... */ })
it=>{ /* ... */ })
it
it" 方法可被外部调用并聚焦 input',)
})
痛点评价
-
setValue : 快速模拟使用者输入并自动触发 input。老实说,
-
trigger : 模拟键盘事件。无需真正按键,
-
wrapper.vm : 调用 expose 的方法,如 focus。
-
attachTo document.body : 若想让 focus 等浏览器行为生效,需要挂载到真 DOM。
从Day3来看,Mock 知识储备
为什么需要 Mock?—现实中的困扰:
`mailApi.getList` 本地网络请求难以控制;当后端不可预知或还未上线时只能用假数据模拟请求返回,否则无法跑单测;同理路由跳转也需隔离,说起来,Mock 可以把这些外部依赖变成可追踪且可预期的假实现。让业务逻辑独立于网络状态而被彻底验证。
- vi.fn 创建假函数 – 痛点梳理 -
ts
const mockFn = vi.fn=>{})
mockFn
expect.toHaveBeenCalled
expect.toHaveBeenCalledWith
expect.not.toHaveBeenCalledTimes
// …etc,
-
好处 :记录调用次数与参数,可用于后续断言。
-
坏处 :若忘记重置,会导致跨 case 泄漏。
ts
beforeEach=>{ vi.clearAllMocks;})
- vi.mock 模块级别替换 – 痛点对照 -
ts
vi.mock{return Promise.resolve}})
-
替换整个模块,使所有 import 都指向 mock 实现。不过,
-
放在文件顶部。以保证 import 前执行。
ts
// 模拟接口失败场景:
vi.mocked?.mockRejectedValueOnce)
await expect).rejects.toThrow
- Mock 路由跳转 – 痛点方法 -
ts
const mockPush = vi.fn
vi.mock{return{push:mockPush}}})
-
验证 push 是否被调用且参数正确,而不会真的跳转页面。
Day4 整合调整 + 覆盖率检查
- 覆盖率工具配置 – 痛感说明 -
bash
pnpm add -D @vitest/coverage-v8 --save-dev
// vite.config.ts 内添加 coverage 配置:
{
test:{
environment:'jsdom'。globals:true,coverage:{
provider:'v8',reporter:,exclude:
}
}
}
注意事项
-
使用
?老实说,No.
-
命令行应为
pnpm run test:coverage —— 否则 Vitest 默认 watch,不退出。
H7‑cover-report 阅读技巧 – 痛感解读:
File % Stmts % Branch % Funcs % Lines
mailStore.ts │ 100 │ 100 │ 100 │ 100
All files │
coverage/index.html
H8‑补充文件示范 – mailList.test.ts
ts
import { describe。it,expect}from'vitest'
import { mount}from '@vue/test-utils'
import MailList from './MailList.vue'
describe =>{
const mockMails=
...
})
常见陷阱
-
子组件需声明
或 才能在父侧通过 name 匹配到。
-
在父侧主动
$emit 子侧事件,而不是父级逻辑。
常用 API 对比表
API / 方法名称
\
用途
\
典型使用案例
\
<#>
assertion methods:
<#>
\
- toBe
- toEqual
- notToThrow
- .resolves/.rejects
\
# Assertion #
# Compare values or errors.
\
Use for exact match or deep comparison.
\
Handle promise resolve/reject.
\
# Example:
`expect.toBe`
`expect.not.toThrow
\
# Tip: Avoid mixing shallow vs deep incorrectly.
\
DOM Interaction APIs:
\
- trigger
- setValue
- find/findAll
\
# Simulate user events.
Use when testing component rendering and interaction.
\
# Example:
`await wrapper.find.trigger`
`input.setValue`
# Tip: Add await for any trigger that updates reactive state.
\
Lifecycle & context APIs:
\
- wrapper.vm
- global.provide / inject
- attachTo
\t\t\t\t\t\\\t-\tnextTick\t\t\\\t-\t$reset\t\t\\\t-\tclearInbox\t\\\t-\tvue Router mocks
\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0
本周
-
*最大的收获*: 测试揭露隐藏隐患,如异步 watch 未同步完成导致误判;说起来,JSDOM 转色彩导致 CSS 样式断言失效等细节。”*
-
*自检清单*
….
.
“掌握好三件套+深度比较+异步等待+挂载+事件+inject/mock”等关键技术。是让后续真正投入生产项目时能够快速编写高质量单测,并避免低质量代码逃过 QA 检查。”
下周计划
第一阶段已基本完成 TS 基础 + Pinia/Vite/Router/Axios + Vue 主要概念 + 响应式性能调整 + 单测五项任务。第9 周开始全栈项目阶段。下周将确认细节安排,并继续推进后端接口集成及前后端联调单测练习。
「Vue前端转全栈实战」系列持续更新,请继续关注!遇到问题欢迎在评论区交流,我将继续记录问题及方法供大家参考。.
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback