Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
488 views
in Technique[技术] by (71.8m points)

javascript - 测试Vuetify(Vue.js)-挂载第二次调用引发错误(Testing Vuetify (Vue.js) - Second call on mount throws error)

I am currently experiencing a behaviour when testing my Vue Application (specifically when vuetify is included).(我目前在测试Vue应用程序时出现行为(特别是在包含vuetify时)。)

I am using Jest as Test Runner but experienced the same behaviour with mocha.(我将Jest用作Test Runner,但是在Mocha中遇到了相同的行为。) The first thing to notice is that the problem only occurs with mount from the @vue/test-utils and not shallowMount.(首先要注意的是,该问题仅发生在@ vue / test-utils的mount中,而不是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).(它也只会在您两次使用mount时发生(我想原因是Vue对象受到污染,但稍后会更多)。) 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.(现在,我的组件只不过是基本v-data-table的包装器,其属性值绑定到其项,并为复选框而非文本提供了一些自定义插槽。) 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(首先,这就是我的测试的第一个变体(基本上是vuetify推荐的样子。请看这里 。由于测试本身并不重要,我只是期望true在这里是真的)) 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.(现在,正如已经在不使用Vue.use(Vuetify)的注释中所述,我将得到以下错误:未注册组件v-data-table。) With it I'm left with the following behaviour(有了它,我有以下行为) Test the first thing runs as expected and succeeds(测试第一件事按预期运行并成功) The the second thing fails the following Error(第二件事失败以下错误) Type Error: Cannot read property '$scopedSlots' of undefined(类型错误:无法读取未定义的属性“ $ scopedSlots”) and fails at mount(....).(并在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.(例如,如果我执行此测试4次,则会发生这种情况。) 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.(我的猜测是Vue类受到某种方式的污染。) So if I look at the documentation for localVue this utility is made to prevent pollution of the global Vue class.(因此,如果我查看有关localVue的文档, 则可以使用该实用程序来防止污染全局Vue类。) 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.(因此,我创建了一个新的localVue实例,并为每个测试创建了vuetify。) and make localVue use vuetify.(并让localVue使用vuetify。) Now this brings me back to the error(现在,这使我回到错误) [Vue warn]: Unknown custom element: - did you register the component correctly?([Vue警告]:未知的自定义元素:-您是否正确注册了组件?) For recursive components, make sure to provide the "name" option.(对于递归组件,请确保提供“名称”选项。) I also experimented with various alterations of injecting vuetify (instantiated) or Vuetify.(我还尝试了注入vuetify(实例化)或Vuetify的各种更改。) using the global Vue.use etc. At the end I'm always left with one of those two behaviours.(使用全局Vue.use等。最后,我总是只剩下这两种行为之一。) 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(我现在还为Vuetify和Vue-Test-Utils创建了Issues,因为我无法想象这是预期的行为,并通过测试作为Repo制作了精简的组件版本) rm-test-mount-fails-on-second-exec(rm测试安装失败第二秒执行) To Reproduce:(重现:) Clone Repo(克隆回购) npm install(npm安装) npm run test:unit(npm运行测试:单位) Versions:(版本:) Vue: 2.6.10(Vue: 2.6.10)
Vue-Test-Utils: 1.0.0-beta.29(Vue-Test-Utils: 1.0.0-beta.29)
Vuetify: 2.1.12(验证: 2.1.12)   ask by relief.melone translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The only thing that seems out of place in your first piece of code is that you are writing Vue.use(Vuetify) and also using an instance of Vuetify when doing mount.(在您的第一段代码中看起来唯一不合时宜的是,您正在编写Vue.use(Vuetify)并且在进行安装时还使用了Vuetify的实例。)

I suggest that you keep the Vue.use(Vuetify) and mount your component like this:(我建议您保留Vue.use(Vuetify)并像这样安装组件:) const wrapper = mount(PermissionTable, { localVue, // vuetify is removed from this object propsData: { value: tableItems } }); On a side note, unit tests generally should use shallowMount .(附带说明一下,单元测试通常应使用shallowMount 。) I am not aware of your use case, but, if possible, please use it instead of mount(我不知道您的用例,但是,如果可能,请使用它而不是mount)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...