测试 Vuetify (Vue.js) - 第二次调用 mount 抛出错误 [英] Testing Vuetify (Vue.js) - Second call on mount throws error

查看:54
本文介绍了测试 Vuetify (Vue.js) - 第二次调用 mount 抛出错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在测试我的 Vue 应用程序时遇到了一种行为(特别是当包含 vuetify 时).我使用 Jest 作为测试运行程序,但在使用 mocha 时遇到了相同的行为.

首先要注意的是,问题只发生在@vue/test-utils 的挂载上,而不是shallowMount.此外,只有在您使用 mount 两次时才会发生(我猜原因是 Vue Object 的污染,但稍后会详细介绍).

现在我的组件只是一个基本的v-data-table 将属性值绑定到它的项目和一些用于复选框而不是文本的自定义插槽.

问题来了.首先,这是我测试的第一个变体的样子(基本上是 vuetify 推荐的.看看 此处.由于测试本身并不重要,因此我只希望此处为 true

从'vue'导入Vue;从 'vuetify' 导入 Vuetify;从@vue/test-utils"导入 { mount, createLocalVue,shallowMount };从 '@/components/PermissionTable.vue' 导入 PermissionTable;从'柴'导入{期望};const localVue = createLocalVue();//Vue.use 不在示例中但离开它会导致错误//数据表未注册Vue.use(Vuetify);describe('Permissiontable.vue', () => {让 vuetify;让 tableItems;beforeEach(() => {表项 = [];vuetify = 新 vuetify();});it('将测试第一件事',() => {const wrapper = mount(PermissionTable, {本地Vue,验证,道具数据:{值:tableItems}});期望(真).成为(真);});it('将测试第二件事',() => {const wrapper = mount(PermissionTable, {本地Vue,验证,道具数据:{值:tableItems}});期望(真).成为(真);});});

现在已经评论过,没有使用 Vue.use(Vuetify) 我会得到组件 v-data-table 未注册的错误.有了它,我就剩下以下行为

  1. 测试第一件事按预期运行并成功
  2. 第二件事失败了以下错误

<块引用><块引用>

类型错误:无法读取未定义的属性$scopedSlots"

并在 mount(....) 时失败.为了使行为更奇怪,如果我调试并停在这一行,在调试控制台中手动运行安装它在第一次失败时也会出现相同的错误.如果我再次运行它,它会起作用.例如,如果我执行此测试 4 次,就会发生这种情况.第一次成功 -> 第二次失败 -> 第三次和第四次再次成功.

现在我确信如果函数得到相同的输入,它们的行为方式是一样的.因此,必须在第一次调用时更改挂载的输入.我的猜测是 Vue 类以某种方式被污染了.因此,如果我查看 localVue 的文档,此实用程序是为了防止全局 Vue 类的污染.所以我把代码改成

从'vue'导入Vue;从 'vuetify' 导入 Vuetify;从@vue/test-utils"导入 { mount, createLocalVue,shallowMount };从 '@/components/PermissionTable.vue' 导入 PermissionTable;从'柴'导入{期望};describe('Permissiontable.vue', () => {让 vuetify;让 tableItems;让 localVue;beforeEach(() => {表项 = [];localVue = createLocalVue();vuetify = 新 vuetify();localVue.use(vuetify);});it('将测试第一件事',() => {const wrapper = mount(PermissionTable, {本地Vue,验证,道具数据:{值:tableItems}});期望(真).成为(真);});it('将测试第二件事',() => {const wrapper = mount(PermissionTable, {本地Vue,验证,道具数据:{值:tableItems}});期望(真).成为(真);});});

所以我为每个测试创建了一个 localVue 和 vuetify 的新实例.并使 localVue 使用 vuetify.现在这让我回到错误

<块引用><块引用>

[Vue 警告]:未知的自定义元素:-您是否正确注册了组件?对于递归组件,请确保提供名称"选项.

我还尝试了注入 vuetify(实例化)或 Vuetify 的各种变化.使用全局 Vue.use 等.最后我总是只剩下这两种行为之一.

现在的解决方法似乎是将每个测试编写在一个有效的文件中,但我认为这是非常糟糕的做法,我想了解这里到底发生了什么.

我现在还为 Vuetify 和 Vue-Test-Utils 创建了问题,因为我无法想象这是预期的行为,以及使用作为 Repo 的测试制作我的组件的精简版本

rm-test-mount-fails-on-second-exec

复制:

  1. 克隆仓库
  2. npm 安装
  3. npm 运行测试:单元

版本:

Vue: 2.6.10
Vue-Test-Utils: 1.0.0-beta.29
Vuetify: 2.1.12

解决方案

坏消息

事实证明,目前这确实是 vue-test-utils 中的一个错误.在我打开问题后,我发现另一个问题很漂亮与我的相似,我很确定其根本原因与我的情况相同.显然这是由于 v.beta.29

中 vue utils 中发生的变化

问题可以在这里找到#1130

好消息

有一种变通方法可以让您的测试再次运行,直到此错误得到解决.您需要使用 sync: false 选项进行挂载,因此顶部示例中的挂载看起来像

const wrapper = mount(PermissionTable, {本地Vue,验证,道具数据:{值:tableItems},同步:假});

我仍然认为这是一个严重的错误,因为无论设置如何,每次运行相同的测试时都应该以相同的方式运行.一有消息说这个问题得到解决,我会尽快更新这篇文章.

I am currently experiencing a behaviour when testing my Vue Application (specifically when vuetify is included). I am using Jest as Test Runner but experienced the same behaviour with mocha.

The first thing to notice is that the problem only occurs with mount from the @vue/test-utils and not shallowMount. Also it only occurs if you use mount twice (I guess the reason is the pollution of the Vue Object but more on that later).

Now my component is manly just a wrapper around a basic v-data-table with the property value bound to its items and some custom slots for checkboxes instead of text.

Now the problem. First this is what the first variant of my test looks like (it's basically how it's recommended by vuetify. take a look here. As the test itsself doesn't really matter I'll just expect true to be true here

import Vue from 'vue';
import Vuetify from 'vuetify';
import { mount, createLocalVue, shallowMount } from '@vue/test-utils';

import  PermissionTable from '@/components/PermissionTable.vue';
import { expect } from 'chai';

const localVue = createLocalVue();

// Vue.use is not in the example but leaving it will cause the error that 
// the data table is not registered
Vue.use(Vuetify);

describe('Permissiontable.vue', () => {
  let vuetify;
  let tableItems;

  beforeEach(() => {
    tableItems = [];
    vuetify = new Vuetify();
  });


  it('will test the first thing',() => {
    const wrapper = mount(PermissionTable, {
      localVue,
      vuetify,
      propsData: {
        value: tableItems
      }
    });

    expect(true).to.be(true);
  });


  it('will test the second thing',() => {
    const wrapper = mount(PermissionTable, {
      localVue,
      vuetify,
      propsData: {
        value: tableItems
      }
    });

    expect(true).to.be(true);
  });
});

Now as already commented without using Vue.use(Vuetify) I'll get the error that the component v-data-table is not registered. With it I'm left with the following behaviour

  1. Test the first thing runs as expected and succeeds
  2. The the second thing fails the following Error

Type Error: Cannot read property '$scopedSlots' of undefined

and fails at mount(....). To make the behaviour even weirder, if I debug and stop at this line, run the mount manually in the debug console it fails as well on the first time with the same error. If I run it again it works. If I for example execute this test 4 times this will happen. 1st will succeed -> 2nd fails -> 3rd and 4th will succeed again.

Now I am sure that functions behave the same way if they get the same input. So the Input to the mount must be altered by the first call. My guess is that the Vue class gets polluted somehow. So if I look at the documentation for localVue this utility is made to prevent pollution of the global Vue class. So I altered my code to

import Vue from 'vue';
import Vuetify from 'vuetify';
import { mount, createLocalVue, shallowMount } from '@vue/test-utils';

import  PermissionTable from '@/components/PermissionTable.vue';
import { expect } from 'chai';

describe('Permissiontable.vue', () => {
  let vuetify;
  let tableItems;
  let localVue;

  beforeEach(() => {
    tableItems = [];
    localVue = createLocalVue();
    vuetify = new Vuetify();
    localVue.use(vuetify);
  });


  it('will test the first thing',() => {
    const wrapper = mount(PermissionTable, {
      localVue,
      vuetify,
      propsData: {
        value: tableItems
      }
    });

    expect(true).to.be(true);
  });


  it('will test the second thing',() => {
    const wrapper = mount(PermissionTable, {
      localVue,
      vuetify,
      propsData: {
        value: tableItems
      }
    });

    expect(true).to.be(true);
  });
});

So I create a new Instance of localVue and vuetify for every test. and make localVue use vuetify. Now this brings me back to the error

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

I also experimented with various alterations of injecting vuetify (instantiated) or Vuetify. using the global Vue.use etc. At the end I'm always left with one of those two behaviours.

Now the workouround seems to be to write each test in a single file which works but I think is really bad practice and I want to understand what exactly happens here.

I also created Issues for Vuetify and Vue-Test-Utils now as I can't imagine this is expected behaviour, as well as making a stripped down Version of my Component with a test as a Repo

rm-test-mount-fails-on-second-exec

To Reproduce:

  1. Clone Repo
  2. npm install
  3. npm run test:unit

Versions:

Vue: 2.6.10
Vue-Test-Utils: 1.0.0-beta.29
Vuetify: 2.1.12

解决方案

The bad news

Turns out this is indeed a bug in vue-test-utils at the moment. After I opened up issues I discovered another issue with a problem pretty similar to mine and I'm pretty sure the root cause for this is the same as in my case. Apperently this is due to a change that happend in the vue utils in v.beta.29

The issue can be found here #1130

The good News

There is a workaround to get your tests working again until this bug is resolved. You need to mount with the option sync: false so mounting in the top example would look like

const wrapper = mount(PermissionTable, {
  localVue,
  vuetify,
  propsData: {
    value: tableItems
  },
  sync: false
});

I still think this is a serious bug as identical tests should behave in the same way every time you run them no matter the settings. I will update this post as soon as there is news that this has been addressed.

这篇关于测试 Vuetify (Vue.js) - 第二次调用 mount 抛出错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆