如何Mock ApolloMutation组件?NuxtApollo测试Wrapper为空报错排查
解决Nuxt Apollo + Vue Test Utils测试时找不到.callMe元素的问题
嘿,我之前踩过类似的坑,你的问题核心在于shallowMount的特性和ApolloMutation组件的处理逻辑上,让我帮你理清楚:
问题根源
当使用shallowMount渲染组件时,它只会渲染当前组件的最外层结构,不会深入渲染子组件(比如ApolloMutation)的内部内容。而你的.callMe按钮是放在ApolloMutation的作用域插槽里的,默认情况下shallowMount完全不会渲染这部分DOM,自然就找不到目标元素了。
只mock$apollo对象是不够的——你还需要让ApolloMutation组件把插槽里的内容暴露出来,供测试代码访问。
解决方案:Mock ApolloMutation组件
我们可以给localVue注册一个mock版本的ApolloMutation组件,让它直接渲染默认插槽的内容,同时传递插槽需要的mutate、loading等参数。
修改后的测试代码如下:
import { createLocalVue, shallowMount } from '@vue/test-utils' import VueApollo from '@nuxtjs/apollo' import Register from '../pages/register/index.vue' describe('Register user', () => { let localVue beforeEach(() => { localVue = createLocalVue() localVue.use(VueApollo, {}) // 关键步骤:Mock ApolloMutation 组件,渲染插槽内容 localVue.component('ApolloMutation', { props: ['mutation', 'variables'], render(h) { // 传递插槽需要的方法和状态,用jest.fn()模拟mutate方法 return this.$scopedSlots.default({ mutate: jest.fn(), loading: false, error: null }) } }) }) it('Should click the register button to register', () => { const wrapper = shallowMount(Register, { localVue }); // 现在能正常找到.callMe按钮了 const callMeButton = wrapper.find('.callMe') callMeButton.trigger('click') expect(2+2).toBe(4) }); });
进阶:测试mutate方法调用
如果你还想验证点击"CreateUser"按钮时mutate是否被正确触发,可以把mock的mutate方法提取出来,方便做断言:
it('Should trigger mutate when create user button is clicked', () => { const mockMutate = jest.fn() // 注册带自定义mutate的mock组件 localVue.component('ApolloMutation', { props: ['mutation', 'variables'], render(h) { return this.$scopedSlots.default({ mutate: mockMutate, loading: false, error: null }) } }) const wrapper = shallowMount(Register, { localVue }) // 找到触发mutate的按钮(不带.callMe类的那个) wrapper.find('button:not(.callMe)').trigger('click') // 断言mutate方法被调用 expect(mockMutate).toHaveBeenCalled() })
这样调整后,你的测试应该就能正常找到DOM元素,同时也能验证核心业务逻辑了。
内容的提问来源于stack exchange,提问作者obi patrick
相关产品推荐
相关产品推荐

