【问题标题】:Vue Test Utils - Unable to correctly mount/shallow mount component, wrapper undefinedVue Test Utils - 无法正确挂载/浅挂载组件,包装器未定义
【发布时间】:2021-05-26 08:23:30
【问题描述】:

我已经尝试了几乎所有我能想到的方法,但我无法正确安装/浅安装我的 vue 组件以进行正确测试。每次我 console.log 包装器时,我都会得到以下打印输出:

VueWrapper {
  isFunctionalComponent: undefined,
  _emitted: [Object: null prototype] {},
  _emittedByOrder: []
}

这个问题类似于这里提出的这个问题:

Vue-test-utils wrapper undefined

我正在使用 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 返回的内容并将其分配给考试变量。最初我返回的是 true,因为这就是我希望 submit() 函数返回的意思,这意味着当我调用exam.submitted 时,我在一个布尔值上调用它,这显然给了我“未定义”。解决方案是准确返回计算属性旨在处理的内容,即一个对象,即 {submitted:true}

因此最终的测试看起来像这样并且返回有效的 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.

【问题讨论】:

    标签: vue.js vue-test-utils


    【解决方案1】:

    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() 返回空字符串在您的根组件上是 v-if="submitted"。计算出来的属性返回undefined,因为getter返回true,所以true.submitted返回undefined

    getter in test.spec.ts:

    getters = {
      getExam: () => {
        return { submitted: true };
      }
    };
    

    【讨论】:

    • 对不起,伙计,它似乎还没有来参加聚会。我已经用最新的错误更新了这个问题。它返回零 HTML,这表明包装器是空的。
    • 问题可能出在 store getter 上。这就是为什么 html 为空的原因。在使用可行的解决方案进行一些测试后,我将更新我的示例。
    • 我希望我在 5 分钟前阅读了此更新。我也刚刚想通了。我已将其全部添加到问题中,并将您的问题标记为正确,因为它是解决方案。非常感谢您的帮助,如果没有“问题可能出在商店吸气剂”的提示,我仍然会被卡住。
    猜你喜欢
    • 1970-01-01
    • 2019-03-07
    • 1970-01-01
    • 2017-08-29
    • 2018-01-21
    • 2017-03-31
    • 1970-01-01
    • 2022-11-25
    • 2018-10-30
    相关资源
    最近更新 更多