From 2f0d978dbffb2839227dbcb0d264438da9169fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E7=9D=BF=20=E5=BC=A0?= Date: Sat, 10 Oct 2026 16:31:39 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BF=AE=E6=AD=A3=E8=AE=A1=E5=88=92=20?= =?UTF-8?q?Task=209=20=E7=89=87=E6=AE=B5=E7=9A=84=20mock=20=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E4=B8=8E=E6=96=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 路径笔误:vi.mock('../../api/materials') 改成 '../api/materials'。测试文件在 src/views/ 下,相对它是一级上跳,原路径会指向仓库根的 api/ 目录 - 补上 materialsApi 替身的具体两行代码,原来只有文字描述、照抄不了 - 两个用例在触发导入前加 fetchMaterials.mockClear():页面 onMounted 就会拉一次 列表,不清的话失败用例的 not.toHaveBeenCalled() 必然失败,成功用例的断言也没区分度 - 成功用例的断言从 toHaveBeenCalled() 收紧成 toHaveBeenCalledWith(1, '', 'all') - 两个用例包进 describe('批量导入'),并给出 beforeEach 里重置替身的写法 验证:从 Task 9 之前的测试文件出发,按文档插入替身、追加用例块,实跑 24 个用例通过。 --- .../plans/2026-10-10-material-bulk-import.md | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/docs/superpowers/plans/2026-10-10-material-bulk-import.md b/docs/superpowers/plans/2026-10-10-material-bulk-import.md index 97ef8fbf..c54e7d6f 100644 --- a/docs/superpowers/plans/2026-10-10-material-bulk-import.md +++ b/docs/superpowers/plans/2026-10-10-material-bulk-import.md @@ -2367,6 +2367,14 @@ git commit -m "feat: 物料导入结果弹窗组件" 在 `frontend/src/views/Materials.test.js` 末尾追加(沿用文件里已有的 `mountMaterials()`、mock 结构): ```js +describe('批量导入', () => { + beforeEach(() => { + materialsApi.importFile.mockReset() + materialsApi.downloadImportTemplate.mockReset() + materialsStore.fetchMaterials.mockReset() + vi.spyOn(ElMessage, 'success').mockImplementation(() => {}) + }) + test('批量导入成功后提示成功并刷新列表', async () => { materialsApi.importFile.mockResolvedValue({ data: { total_rows: 2, success_rows: 2, failed_rows: 0, errors: [] } @@ -2374,6 +2382,8 @@ git commit -m "feat: 物料导入结果弹窗组件" const wrapper = mountMaterials() await flushPromises() + // 挂载时 onMounted 已经拉过一次列表,清掉才能断言“导入后又拉了一次” + materialsStore.fetchMaterials.mockClear() await setupState(wrapper).handleImportFile({ target: { files: [new File(['x'], '物料.xlsx')], value: '物料.xlsx' } @@ -2381,7 +2391,7 @@ git commit -m "feat: 物料导入结果弹窗组件" await flushPromises() expect(materialsApi.importFile).toHaveBeenCalled() - expect(materialsStore.fetchMaterials).toHaveBeenCalled() + expect(materialsStore.fetchMaterials).toHaveBeenCalledWith(1, '', 'all') expect(ElMessage.success).toHaveBeenCalledWith('成功导入 2 条物料') wrapper.unmount() }) @@ -2402,6 +2412,7 @@ git commit -m "feat: 物料导入结果弹窗组件" const wrapper = mountMaterials() await flushPromises() + materialsStore.fetchMaterials.mockClear() await setupState(wrapper).handleImportFile({ target: { files: [new File(['x'], '物料.xlsx')], value: '物料.xlsx' } @@ -2412,9 +2423,19 @@ git commit -m "feat: 物料导入结果弹窗组件" expect(materialsStore.fetchMaterials).not.toHaveBeenCalled() wrapper.unmount() }) +}) ``` -**注意:** `Materials.test.js` 目前 mock 的是 `vi.mock('../stores/materials')` 与 `vi.mock('../../api/masterData')`,需要在顶部补 `vi.mock('../../api/materials')`,导出 `materialsApi`(含 `importFile`/`downloadImportTemplate` 两个 `vi.fn()`);`ElMessage` 的 spy 若尚未建立,按文件里既有的 `vi.mock('element-plus')` 方式补齐。 +**注意:** `Materials.test.js` 里已 mock 的是 `vi.mock('../stores/materials')` 与 `vi.mock('../api/masterData')`——路径相对 `src/views/`,是一级上跳。顶部要补两行(与文件里其它替身放在一起): + +```js +const materialsApi = vi.hoisted(() => ({ importFile: vi.fn(), downloadImportTemplate: vi.fn() })) +vi.mock('../api/materials', () => ({ materialsApi })) +``` + +`ElMessage` 不需要 mock 整个模块,文件里既有的写法是 `vi.spyOn(ElMessage, 'success').mockImplementation(() => {})`,新 describe 的 `beforeEach` 里照做即可。 + +**另外:** 页面 `onMounted` 就会调 `fetchMaterials()`,所以两个用例在触发导入前都要 `mockClear()`——不清的话失败用例的 `not.toHaveBeenCalled()` 必然失败,成功用例的 `toHaveBeenCalled()` 也没有区分度。 - [ ] **Step 2: 跑测试确认失败**