Vue.js - 具有复杂子项的单元测试组件

Posted

技术标签:

【中文标题】Vue.js - 具有复杂子项的单元测试组件【英文标题】:Vue.js - Unit testing component with complex children 【发布时间】:2020-06-09 14:43:12 【问题描述】:

让我们假设一个基本的 Bootstrap 驱动的 html 表单作为自定义 Vue 组件 MyForm.vue 的一部分

<template>
  <form>
    <div class="form-group">
      <label for="email">Email address</label>
      <input type="email" class="form-control" id="email">
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
</template>

用于测试模板是否成功呈现的单元测试非常简单

describe('MyForm', () => 

  let wrapper;

  beforeEach(...);

  it('Should be rendered', () => 

    let field = wrapper.find('#email');
    expect(field.element.value).toEqual('');
  );
);

这行有效field.element.value 有效,因为field.element 是具有value 属性的本机类型HtmlInputElement

如果我想访问复杂组件的属性,比如说b-form-input,Bootstrap-Vue 的默认输入元素怎么办? b-form-inputBFormInput 类型的怎么处理呢?只需将HtmlElement 转换为BFormInput

<template>
  <b-form>
    <b-form-group label="Email">
      <b-form-input type="email" id="email"></b-form-input>
    </b-form-group>
    <b-button type="submit" variant="primary">Submit</button>
  </b-form>
</template>

如何测试非原生组件?特别是类型安全意味着 TypeScript。有什么想法吗?

编辑 03/01/2020

根据muka.gergely 的回答,我找到了this 文章。 shallowMount 默认情况下会存根所有子组件,这也阻止了事件处理。此外,shallowMount 允许手动 unstub 组件,在我的情况下,可以 unstub b-formb-button 以提交事件测试。

const stubs =  // Originally intended to provide custom stubs, here used to unstub components
  BButton,
  BForm,
;

wrapper = shallowMount<MyComponent>(MyComponent, stubs);

这会影响这些组件被渲染而不是存根。像b-form-input 这样的所有剩余组件仍然会自动存根。

【问题讨论】:

【参考方案1】:

您必须在测试元素之前mount。您不会测试您编写的 Vue 组件,而是测试渲染的输出。

你应该添加 vue-test-utils 然后你的单元测试库(JestMocha 都很好支持)。

你可以在这里找到 vue-test-utils:https://www.npmjs.com/package/@vue/test-utils 更多关于 Vue 单元测试:https://vuejs.org/v2/guide/unit-testing.html 更多关于 vue-test-utils:https://vue-test-utils.vuejs.org/guides/#getting-started

这是 App.vue 的基本单元测试(使用 Vuetifyvue-router):

import Vue from 'vue'
import  shallowMount, createLocalVue  from '@vue/test-utils'
import Vuetify from 'vuetify'
import VueRouter from 'vue-router'
import App from '@/App';

Vue.use(Vuetify)

const localVue = createLocalVue()
localVue.use(VueRouter)
const router = new VueRouter()

describe('App.vue', () => 
    let vuetify

    beforeEach(() => 
        vuetify = new Vuetify()
    )

    it('mounts and renders', () => 
        const wrapper = shallowMount(App,  localVue, vuetify, router );

        expect(wrapper.html()).toBeTruthy();
    );
);

您可以看到我使用了shallowMount(),因为我对测试 App.vue 的子级不感兴趣(它们都有各自的单元测试)。如果我是,那么我应该改用mount()

【讨论】:

是的,我已经用过shallowMount... 这是否意味着我在单元测试期间对渲染输出不感兴趣? shallowMount 只渲染正在测试的组件,而不是子组件

以上是关于Vue.js - 具有复杂子项的单元测试组件的主要内容,如果未能解决你的问题,请参考以下文章

测试用例要素

单测方法论---1

如何对使用 nuxt-i18n 的 Vue.js 组件进行单元测试

如何对第一个Vue.js组件进行单元测试 (下)

前端单元测试笔记 —— 覆盖率篇

带有函数调用的 vue.js 单元测试 v-slot