Vue Test Utils - 无法正确 mount/shallow 挂载组件,包装器未定义
Vue Test Utils - Unable to correctly mount/shallow mount component, wrapper undefined
我已经尝试了几乎所有我能想到的方法,但我无法正确 mount/shallow 挂载我的 vue 组件以进行正确测试。每次我 console.log 包装器时,我都会打印出以下内容:
VueWrapper {
isFunctionalComponent: undefined,
_emitted: [Object: null prototype] {},
_emittedByOrder: []
}
这个问题类似于这里问的这个问题:
我正在使用 Vuetify、Vuex 和 Vue 路由器。我的test.spec.ts如下:
import { shallowMount, createLocalVue, mount } from "@vue/test-utils"
import Vuex from "vuex"
import Vuetify from "vuetify"
import VueRouter from "vue-router"
import TheExamAnswer from "@/components/common/TheExamAnswer.vue"
describe("TheExamAnswer.vue", () => {
const localVue = createLocalVue()
let getters: any
let store: any
let vuetify: any
let router: any
beforeEach(() => {
localVue.use(Vuex)
localVue.use(Vuetify)
localVue.use(VueRouter)
getters = {
getExam: () => true,
}
store = new Vuex.Store({
modules: {
// Need to add FlightPlanning for name spacing
FlightPlanning: {
namespaced: true,
getters,
},
},
})
vuetify = new Vuetify()
router = new VueRouter()
})
it("Renders the element if the exam has been submitted", () => {
const wrapper = mount(TheExamAnswer, { localVue, store, router })
console.log("This is the HTML", wrapper.html())
expect(wrapper.text()).toContain("Show Answer")
})
})
我的视图组件很简单,代码如下:
<template>
<div v-if="submitted" class="div">
<v-btn @click="answerHidden = !answerHidden" class="mb-10"
>Show Answer</v-btn
>
<div v-if="!answerHidden">
<slot name="questionAnswer"></slot>
</div>
</div>
</template>
<script>
export default {
data: () => {
return {
answerHidden: true,
}
},
computed: {
submitted() {
const exam = this.$store.getters["FlightPlanning/getExam"]
return exam.submitted
},
},
}
</script>
<style></style>
更新: 我已经从下面的答案中添加了建议,但是现在我收到了以下消息。
TheExamAnswer.vue
✕ Renders the element if the exam has been submitted (49ms)
● TheExamAnswer.vue › Renders the element if the exam has been submitted
expect(received).toContain(expected) // indexOf
Expected substring: "Show Answer"
Received string: ""
38 | const wrapper = mount(TheExamAnswer, { localVue, store, router })
39 | console.log("This is the HTML", wrapper.html())
> 40 | expect(wrapper.text()).toContain("Show Answer")
| ^
41 | })
42 | })
43 |
at Object.it (tests/unit/test.spec.ts:40:28)
console.error node_modules/vuetify/dist/vuetify.js:43612
[Vuetify] Multiple instances of Vue detected
See https://github.com/vuetifyjs/vuetify/issues/4068
If you're seeing "$attrs is readonly", it's caused by this
console.log tests/unit/test.spec.ts:39
This is the HTML
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
如您所见,HTML 是空白的,因此我推测这也是测试失败的原因,因为接收到的字符串是“”。
解 -
我想通了。由于没有正确查看计算 属性 的逻辑,该错误代表我。
在我的测试中我有:
getters = {
getExam: () => true,
}
在我的组件中我有:
computed: {
submitted() {
const exam = this.$store.getters["FlightPlanning/getExam"]
return exam.submitted
},
如果您查看计算 属性 的逻辑,它将从 getter 中获取 returned 并将其分配给考试变量。最初我是 returning true,因为这就是我想要 return 的 submitted() 函数,这意味着当我调用 exam.submitted 时,我是在一个布尔值上调用它,这显然给了我“不明确的”。解决方案是 return 正是计算的 属性 旨在处理的对象,即 {submitted:true}
因此最终测试看起来像这样 return 有效 HTML。
import { shallowMount, createLocalVue, mount } from "@vue/test-utils"
import Vuex from "vuex"
import Vuetify from "vuetify"
import VueRouter from "vue-router"
import TheExamAnswer from "@/components/common/TheExamAnswer.vue"
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Vuetify)
localVue.use(VueRouter)
describe("test.vue", () => {
let getters: any
let store: any
let vuetify: any
let router: any
beforeEach(() => {
getters = {
getExam: () => {
return { submitted: true }
},
}
store = new Vuex.Store({
modules: {
// Need to add FlightPlanning for name spacing
FlightPlanning: {
namespaced: true,
getters,
},
},
})
vuetify = new Vuetify()
router = new VueRouter()
})
it("Renders the element if the exam has been submitted", () => {
const wrapper = mount(TheExamAnswer, { localVue, vuetify, store, router })
console.log("This is the HTML", wrapper.html())
})
})
这给了我以下结果:
console.log tests/unit/test.spec.ts:44
This is the HTML <div><button type="button" class="mb-10 v-btn v-btn--contained theme--light v-size--default"><span class="v-btn__content">Show Answer</span></button>
<!---->
</div>
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.235s
Ran all test suites.
console.log 带有奇怪的包装器或元素输入是正常行为。我 运行 对您的组件进行了测试,一切正常。
it("Renders the element if the exam has been submitted", () => {
const wrapper = mount(TheExamAnswer, { localVue, store, router });
expect(wrapper.text()).toContain("Show Answer");
});
如果你想 console.log html 在你的包装器中:
console.log(wrapper.html())
更新: 原因,为什么 wrapper.html()
return 空字符串在根组件上是 v-if="submitted"
。计算出来的属性returnundefined
,因为getterreturntrue
,所以true.submitted
returnundefined
Getter 在 test.spec.ts
:
getters = {
getExam: () => {
return { submitted: true };
}
};
我已经尝试了几乎所有我能想到的方法,但我无法正确 mount/shallow 挂载我的 vue 组件以进行正确测试。每次我 console.log 包装器时,我都会打印出以下内容:
VueWrapper {
isFunctionalComponent: undefined,
_emitted: [Object: null prototype] {},
_emittedByOrder: []
}
这个问题类似于这里问的这个问题:
我正在使用 Vuetify、Vuex 和 Vue 路由器。我的test.spec.ts如下:
import { shallowMount, createLocalVue, mount } from "@vue/test-utils"
import Vuex from "vuex"
import Vuetify from "vuetify"
import VueRouter from "vue-router"
import TheExamAnswer from "@/components/common/TheExamAnswer.vue"
describe("TheExamAnswer.vue", () => {
const localVue = createLocalVue()
let getters: any
let store: any
let vuetify: any
let router: any
beforeEach(() => {
localVue.use(Vuex)
localVue.use(Vuetify)
localVue.use(VueRouter)
getters = {
getExam: () => true,
}
store = new Vuex.Store({
modules: {
// Need to add FlightPlanning for name spacing
FlightPlanning: {
namespaced: true,
getters,
},
},
})
vuetify = new Vuetify()
router = new VueRouter()
})
it("Renders the element if the exam has been submitted", () => {
const wrapper = mount(TheExamAnswer, { localVue, store, router })
console.log("This is the HTML", wrapper.html())
expect(wrapper.text()).toContain("Show Answer")
})
})
我的视图组件很简单,代码如下:
<template>
<div v-if="submitted" class="div">
<v-btn @click="answerHidden = !answerHidden" class="mb-10"
>Show Answer</v-btn
>
<div v-if="!answerHidden">
<slot name="questionAnswer"></slot>
</div>
</div>
</template>
<script>
export default {
data: () => {
return {
answerHidden: true,
}
},
computed: {
submitted() {
const exam = this.$store.getters["FlightPlanning/getExam"]
return exam.submitted
},
},
}
</script>
<style></style>
更新: 我已经从下面的答案中添加了建议,但是现在我收到了以下消息。
TheExamAnswer.vue
✕ Renders the element if the exam has been submitted (49ms)
● TheExamAnswer.vue › Renders the element if the exam has been submitted
expect(received).toContain(expected) // indexOf
Expected substring: "Show Answer"
Received string: ""
38 | const wrapper = mount(TheExamAnswer, { localVue, store, router })
39 | console.log("This is the HTML", wrapper.html())
> 40 | expect(wrapper.text()).toContain("Show Answer")
| ^
41 | })
42 | })
43 |
at Object.it (tests/unit/test.spec.ts:40:28)
console.error node_modules/vuetify/dist/vuetify.js:43612
[Vuetify] Multiple instances of Vue detected
See https://github.com/vuetifyjs/vuetify/issues/4068
If you're seeing "$attrs is readonly", it's caused by this
console.log tests/unit/test.spec.ts:39
This is the HTML
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
如您所见,HTML 是空白的,因此我推测这也是测试失败的原因,因为接收到的字符串是“”。
解 -
我想通了。由于没有正确查看计算 属性 的逻辑,该错误代表我。
在我的测试中我有:
getters = {
getExam: () => true,
}
在我的组件中我有:
computed: {
submitted() {
const exam = this.$store.getters["FlightPlanning/getExam"]
return exam.submitted
},
如果您查看计算 属性 的逻辑,它将从 getter 中获取 returned 并将其分配给考试变量。最初我是 returning true,因为这就是我想要 return 的 submitted() 函数,这意味着当我调用 exam.submitted 时,我是在一个布尔值上调用它,这显然给了我“不明确的”。解决方案是 return 正是计算的 属性 旨在处理的对象,即 {submitted:true}
因此最终测试看起来像这样 return 有效 HTML。
import { shallowMount, createLocalVue, mount } from "@vue/test-utils"
import Vuex from "vuex"
import Vuetify from "vuetify"
import VueRouter from "vue-router"
import TheExamAnswer from "@/components/common/TheExamAnswer.vue"
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Vuetify)
localVue.use(VueRouter)
describe("test.vue", () => {
let getters: any
let store: any
let vuetify: any
let router: any
beforeEach(() => {
getters = {
getExam: () => {
return { submitted: true }
},
}
store = new Vuex.Store({
modules: {
// Need to add FlightPlanning for name spacing
FlightPlanning: {
namespaced: true,
getters,
},
},
})
vuetify = new Vuetify()
router = new VueRouter()
})
it("Renders the element if the exam has been submitted", () => {
const wrapper = mount(TheExamAnswer, { localVue, vuetify, store, router })
console.log("This is the HTML", wrapper.html())
})
})
这给了我以下结果:
console.log tests/unit/test.spec.ts:44
This is the HTML <div><button type="button" class="mb-10 v-btn v-btn--contained theme--light v-size--default"><span class="v-btn__content">Show Answer</span></button>
<!---->
</div>
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.235s
Ran all test suites.
console.log 带有奇怪的包装器或元素输入是正常行为。我 运行 对您的组件进行了测试,一切正常。
it("Renders the element if the exam has been submitted", () => {
const wrapper = mount(TheExamAnswer, { localVue, store, router });
expect(wrapper.text()).toContain("Show Answer");
});
如果你想 console.log html 在你的包装器中:
console.log(wrapper.html())
更新: 原因,为什么 wrapper.html()
return 空字符串在根组件上是 v-if="submitted"
。计算出来的属性returnundefined
,因为getterreturntrue
,所以true.submitted
returnundefined
Getter 在 test.spec.ts
:
getters = {
getExam: () => {
return { submitted: true };
}
};