使用 Vue Test Utils 将模拟方法传递给 mount/shallowMount

J D*_*awg 5 vue.js jestjs vue-test-utils

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

我尝试过 mount 和shallowMount、创建/安装的钩子,也尝试过直接调用函数,而不是在创建/安装的钩子内部调用。

// 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
  })
})
Run Code Online (Sandbox Code Playgroud)
TestComponent.vue

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

  methods: {
    setLoading () {
      console.log('Original method'); // Never logs
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Met*_*lmi 2

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

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

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

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