测试 Vue 组件 - 模拟状态和方法

Posted

技术标签:

【中文标题】测试 Vue 组件 - 模拟状态和方法【英文标题】:Testing Vue Components - Mocking State and Methods 【发布时间】:2019-03-07 00:25:49 【问题描述】:

我一直在尝试对 Vue 组件进行单元测试,但我似乎无法完全弄清楚如何模拟/存根存储对象和调用异步 API 的方法。

这是我们拥有的 Vue 组件的示例:

import  mapState, mapGetters  from 'vuex'
import router from 'components/admin/router'

export default 
name: 'Users',
computed: 
    ...mapState('admin', [
        'users',
    ]),
    ...mapGetters(
        requestInProgress: 'requestInProgress',
    ),
,
data: function() 
    return 
        filterTerm: '',
        usersLoaded: false,
    
,
methods:         
    getUsers(filter) 
            this.$store.dispatch('admin/getUserList', filter)
                .then(res => 
                    this.usersLoaded = true
                )
                .catch(e => 
                    this.$toast.error(
                        title: 'Failed to retrieve data',
                        message: this.$options.filters.normaliseError(e),
                    )
                )            
    ,
,
mounted() 
    this.getUsers('*')
,

这就是我要写的测试。如果不实际尝试断言任何内容,我什至无法让测试干净地运行

import Vue from 'vue'
import  shallowMount  from '@vue/test-utils'
import Users from 'components/admin/pages/user/users.vue'

describe('Users Vue', () => 
    it('Page Should Load', () => 
     const mockResponse = 
          data: [
            "id": "1",
            "emailAddress": "beakersoft@gmail.com",
            "firstName": "Luke",
            "lastName": "Niland",
            "staffNumber": "12345",
            "phoneNumber": "07707 999999",
            "active": true
        
    ];

    let actions
    let store

    beforeEach(() => 
        actions = 
            'admin/getUserList': sinon.stub()                      
                  .returns(Promise.resolve(mockResponse))
        
        store = new Vuex.Store(
            state: ,
            actions
        )
    )                   

    const wrapper = shallowMount(Users,  store )

    const h5 = wrapper.find('h5')
    expect(h5.text()).toBe('User Administration')  
  )
 )

我倾向于返回的错误是关于未定义的项目,通常在这种情况下,$store.dispatchundefined。我觉得我在某处的嘲笑中遗漏了一些东西,或者在坐骑上调用 getUsers() 的事实使它绊倒了。

【问题讨论】:

谁调用 filterUsers?也许 filterUsers 的这个上下文是错误的? 复制粘贴代码失败,它在组件的挂载上被调用。更新了代码 您在测试中是否使用了localVue 实例?我想,如果没有它,您的模拟商店将不会附加任何东西。见here。 【参考方案1】:

为了像您在示例中那样测试模拟 Vuex 的 Vue 组件,可以在您 shallowMount 组件时将模拟 store 传递给 Vue,所以:

shallowMount(Users,  store )

但是这个模拟 store 也需要安装到基本的 Vue 构造函数。为此,您必须将其传递给 - localVuelocalVue 是一个作用域的 Vue 构造函数,您可以在测试范围内对其进行更改,而不会影响应用程序中实际使用的全局 Vue 构造函数。

此外,在您的具体情况下,您既没有导入也没有安装 Vuex。

然后,要正确配置您的测试,您需要:

    通过调用 Vue Test Utils 实用程序 createLocalVue 函数创建一个 localVue 实例并在其上安装 Vuex:
    import  shallowMount, createLocalVue  from '@vue/test-utils'
    import Vuex from 'vuex'

    //creating the local Vue instance for testing
    const localVue = createLocalVue()

    //mounting Vuex to it
    localVue.use(Vuex)
    更改您的 shallowMount 函数,同时将 localVue 实例添加到有效负载:
 const wrapper = shallowMount(Users,  store, localVue )

有关官方文档参考,请参阅here。

另一个关于 Vue 测试的有用资源是 this book(对于您的具体情况,请参阅第 7 章)和 its GitHub repository

【讨论】:

【参考方案2】:

您必须为您的测试创建一个本地 Vue 并安装 Vuex 插件:

import  shallowMount, createLocalVue  from '@vue/test-utils'
import Vuex from 'vuex'

const localVue = createLocalVue()

localVue.use(Vuex)

const wrapper = shallowMount(...)

【讨论】:

以上是关于测试 Vue 组件 - 模拟状态和方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jest 在 Vue 中为组件中的方法编写单元测试

使用 Jest 测试 Vue3 组件时如何模拟计算属性

如何模拟被 vue 指令触发的方法?

Vue-admin工作整理: actions(模拟接口请求实现组件字段更新)

Vue-test-utils 模拟从另一个组件获取响应

开玩笑地模拟 useDispatch 并在功能组件中使用该调度操作来测试参数