如何在Apollo+Nuxt环境下测试Vue组件的async fetch()方法
问题原因&解法
你代码里存在3个核心错误:
- 测试用例的test回调没有声明
async,无法使用await处理异步逻辑 - 测试时没有给组件注入mock的
$apollo依赖,导致组件运行时访问this.$apollo报错 - 测试作用域下的
this不是组件实例,访问组件实例需要用wrapper.vm,且fetch方法需要手动触发并等待执行完成
方案1:仅测试variables构造逻辑(单元测试首选,无外部依赖)
直接mock Apollo客户端的query方法,捕获调用时传入的参数做校验,不需要真实发起GQL请求,测试速度最快。
修改后的测试代码如下:
// ProductList.spec.js import { shallowMount } from '@vue/test-utils' import ProductListing from '~/components/blocks/ProductListing.vue' import PRODUCT_LISTING_BLOCK_QUERY from '~/queries/productListingBlock.gql' import '@testing-library/jest-dom' const directives = { interpolation: () => {} } // 预设模拟的返回数据 const mockProducts = [ { id: 1, name: '测试商品1', sku: 'ms239' }, { id: 2, name: '测试商品2', sku: 'mk332' } ] // 存储Apollo query的调用参数,用于后续校验 let capturedQueryParams = null const mocks = { $md: { render: value => value }, // 新增mock $apollo依赖 $apollo: { provider: { clients: { defaultClient: { query: (params) => { // 捕获调用参数 capturedQueryParams = params // 返回模拟数据 return Promise.resolve({ data: { allProducts: mockProducts } }) } } } } } } describe('ProductListing', () => { // 测试回调加async test('fetch方法构造variables正确', async () => { const testVariables = { maxItems: 10, matchSkus: 'ms239,mk332,as484', matchTags: 'tag1,tag2,tag3', matchCategories: '111,222,333,444' } const wrapper = shallowMount(ProductListing, { propsData: testVariables, stubs: ['ProductTileList'], directives, mocks }) // 手动调用fetch方法,等待执行完成 await wrapper.vm.fetch() // 校验variables构造结果 expect(capturedQueryParams.variables).toEqual({ limit: 10, skus: ['ms239', 'mk332', 'as484'], tags: ['tag1', 'tag2', 'tag3'], categories: [111, 222, 333, 444] }) // 校验query正确 expect(capturedQueryParams.query).toBe(PRODUCT_LISTING_BLOCK_QUERY) // 校验context配置正确 expect(capturedQueryParams.context.clientName).toBe('some-company') // 校验组件products赋值正确 expect(wrapper.vm.products).toEqual(mockProducts) }) })
方案2:增加返回数据schema校验
如果需要校验返回数据结构符合预期,可以引入Zod等校验库定义schema,对返回的数据做格式校验:
- 先安装依赖:
npm i zod -D - 在测试文件中新增schema定义:
import { z } from 'zod' // 定义返回商品的结构schema,可按实际业务字段调整 const ProductSchema = z.object({ id: z.number(), name: z.string(), sku: z.string(), price: z.number() }) const ProductsResponseSchema = z.array(ProductSchema)
- 在测试用例中新增校验逻辑:
// 校验返回数据格式符合schema expect(() => ProductsResponseSchema.parse(wrapper.vm.products)).not.toThrow()
方案3:真实请求Apollo实例做集成测试
如果需要实际调用GQL接口测试完整链路,你需要在测试环境初始化你的Apollo客户端,然后把真实的客户端实例传入mock的$apollo配置中即可,注意需要提前处理测试环境的接口鉴权、跨域等问题。
内容的提问来源于stack exchange,提问作者MaylorTaylor
相关产品推荐
相关产品推荐

