首页 > 解决方案 > 使用 Vue Test Utils 将模拟方法传递给 mount/shallowMount

问题描述

有人可以向我解释为什么在一个methods对象中传递的模拟函数不能通过shallowMount包装对象在测试中访问,而是必须首先创建一个变量作为对模拟函数的引用来访问?

我已经尝试过 mount 和 shallowMount,created/mounted hooks 以及直接调用函数,而不是在 created/mounted hook 内部。

// TestComponent.spec.js

import TestComponent from '@/components/TestComponent'
import { shallowMount, createLocalVue } from '@vue/test-utils'

const localVue = createLocalVue()

const setLoadingMock = jest.fn() // mock function that is accessible in the test

function createWrapper () {

  const defaultMountingOptions = {
    localVue,
    methods: {
      setLoading: setLoadingMock
    }
  }

  return shallowMount(TestComponent, defaultMountingOptions)
}

describe('TestComponent.vue', () => {

  let wrapper

  beforeEach(() => {
    wrapper = createWrapper()
  });

  it('will call setLoading', () => {
    expect(wrapper.vm.setLoading).toHaveBeenCalled() 
    // FAILS. Console message:
    // Matcher error: received value must be a mock or spy function

    // Received has type:  function
    // Received has value: [Function bound mockConstructor]
  })

  it('will call setLoading', () => {
    expect(setLoadingMock).toHaveBeenCalled() // PASSES
  })
})
TestComponent.vue

export default {
  name: 'TestComponent',
  mounted () {
    this.setLoading()
  },

  methods: {
    setLoading () {
      console.log('Original method'); // Never logs
    }
  }
}

标签: vue.jsjestjsvue-test-utils

解决方案


mount或者shallowMount在这种情况下并不重要。mount意味着 test 将挂载组件及其子组件,而shallowMount将仅挂载组件并存根其子组件。

您正在模拟该setLoading方法,这意味着您正在用模拟替换原始方法。意思是,当setLoading方法被调用时,它不会运行你的组件中的代码,而是来自测试模拟的代码——在这种情况下jest.fn()

模拟的目的是检查被模拟的方法是否被正确调用。

另外,wrapper.vm.setLoading调用setLoading方法。


推荐阅读