开玩笑+ Vue Test Utils:无法读取未定义的属性(读取“组件”)
我对测试 UI 元素还很陌生,在这里我很茫然。我有一个组件 ProjectDashboardView
,它在挂载时从 API 获取一些信息,并使用获取的信息呈现一系列 ProjectDashboardCard
组件。我正在模拟测试中的 API 调用,使用 flush-promises
等待所有承诺在断言之前得到解决。但是,我收到此错误:
● projectDashboardView › displays ProjectDashboardCards corresponding to all the repositories fetched
TypeError: Cannot read properties of undefined (reading 'component')
14 | describe('projectDashboardView', () => {
15 | it('displays ProjectDashboardCards corresponding to all the repositories fetched', async () => {
> 16 | const wrapper = await mount(ProjectDashboardView, {
| ^
17 | router,
18 | localVue,
19 | mocks: {
at remapInternalIcon (node_modules/vuetify/dist/webpack:/Vuetify/src/util/helpers.ts:233:39)
at VueComponent.getIcon (node_modules/vuetify/dist/webpack:/Vuetify/src/components/VIcon/VIcon.ts:72:31)
at Proxy.render (node_modules/vuetify/dist/webpack:/Vuetify/src/components/VIcon/VIcon.ts:217:23)
at VueComponent.Vue._render (node_modules/vue/dist/vue.runtime.common.dev.js:3559:22)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:21)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:14057:21)
这是测试和组件的代码:
ProjectDashboardView.spec.js
import { mount, createLocalVue } from '@vue/test-utils'
import { SERVICES } from '@/utils/common'
import VueRouter from 'vue-router'
import router from '@/router'
import flushPromises from 'flush-promises'
import ProjectDashboardView from '@/components/ProjectDashboard/ProjectDashboardView.vue'
import ProjectDashboardCard from '@/components/ProjectDashboard/ProjectDashboardCard.vue'
jest.mock('@/services/finderService')
const localVue = createLocalVue()
localVue.use(VueRouter)
describe('projectDashboardView', () => {
it('displays ProjectDashboardCards corresponding to all the repositories fetched', async () => {
const wrapper = mount(ProjectDashboardView, {
router,
localVue,
mocks: {
$store: {
state: {
user: {
name: '',
// Array of IDs
repositories: [1, 2],
// Services the user is using to test code quality in their projects
services: SERVICES,
},
},
},
},
})
await flushPromises()
const children = wrapper.findAllComponents(ProjectDashboardCard)
expect(children.length).toBeGreaterThan(0)
})
})
ProjectDashboardView.js
<template>
<v-container class="grid">
<project-dashboard-card
v-for="(value, name) in latestReports"
:key="name"
:repository="value"
/>
<the-add-project-button />
</v-container>
</template>
<script>
import finderService from '@/services/finderService'
import ProjectDashboardCard from '@/components/ProjectDashboard/ProjectDashboardCard'
import TheAddProjectButton from '@/components/ProjectDashboard/TheAddProjectButton'
import { mapState } from 'vuex'
export default {
name: 'ProjectDashboardView',
components: {
ProjectDashboardCard,
TheAddProjectButton,
},
data() {
return {
latestReports: [],
}
},
computed: {
...mapState(['user']),
},
mounted() {
this.fetchLatestReports()
},
methods: {
fetchLatestReports() {
const reportTuples = []
for (const repo of this.user.repositories) {
for (const service of this.user.services) {
reportTuples.push([service, repo])
}
}
const allReports = Promise.all(
reportTuples.map(t => finderService.find(t[0], t[1], true))
)
const latestReports = {}
allReports
.then(responses => {
const filteredResponses = responses.filter(
response => response.data.length > 0
)
filteredResponses.forEach(response => {
if (!latestReports[`repo${response.repoID}`]) {
latestReports[`repo${response.repoID}`] = {}
}
if (!latestReports[`repo${response.repoID}`].repoName) {
latestReports[`repo${response.repoID}`].repoName =
response.data[0].project_name
}
if (!latestReports[`repo${response.repoID}`].services) {
latestReports[`repo${response.repoID}`].services =
{}
}
latestReports[`repo${response.repoID}`].services[
response.service
] = response.data[0]
})
this.latestReports = latestReports
})
.catch(err => console.log(err))
},
},
}
</script>
以防万一,这里也是 API 调用模拟的代码:
import sonarqubeReport from './fixtures/find.sonarqube.1.json'
import gitleaksReport from './fixtures/find.gitleaks.1.json'
import dependencycheckReport from './fixtures/find.dependencycheck.1.json'
import hadolintReport from './fixtures/find.hadolint.1.json'
import trivyReport from './fixtures/find.trivy.1.json'
const mockGetResponse = service => {
switch (service) {
case 'sonarqube':
return sonarqubeReport
case 'gitleaks':
return gitleaksReport
case 'dependencycheck':
return dependencycheckReport
case 'hadolint':
return hadolintReport
case 'trivy':
return trivyReport
default:
break
}
}
const finderService = {
find: service => Promise.resolve({ body: mockGetResponse(service) }),
}
export default finderService
I'm pretty new to testing UI elements and I'm at a loss here. I have a component, ProjectDashboardView
, that fetches some information from an API on mount and renders a series of ProjectDashboardCard
components with that fetched information. I'm mocking the API call on the tests, using flush-promises
to wait for all promises to be resolved before assertion. However, I'm getting this error:
● projectDashboardView › displays ProjectDashboardCards corresponding to all the repositories fetched
TypeError: Cannot read properties of undefined (reading 'component')
14 | describe('projectDashboardView', () => {
15 | it('displays ProjectDashboardCards corresponding to all the repositories fetched', async () => {
> 16 | const wrapper = await mount(ProjectDashboardView, {
| ^
17 | router,
18 | localVue,
19 | mocks: {
at remapInternalIcon (node_modules/vuetify/dist/webpack:/Vuetify/src/util/helpers.ts:233:39)
at VueComponent.getIcon (node_modules/vuetify/dist/webpack:/Vuetify/src/components/VIcon/VIcon.ts:72:31)
at Proxy.render (node_modules/vuetify/dist/webpack:/Vuetify/src/components/VIcon/VIcon.ts:217:23)
at VueComponent.Vue._render (node_modules/vue/dist/vue.runtime.common.dev.js:3559:22)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:21)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at createChildren (node_modules/vue/dist/vue.runtime.common.dev.js:6077:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5978:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at init (node_modules/vue/dist/vue.runtime.common.dev.js:3131:13)
at createComponent (node_modules/vue/dist/vue.runtime.common.dev.js:6002:9)
at createElm (node_modules/vue/dist/vue.runtime.common.dev.js:5949:9)
at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.runtime.common.dev.js:6499:7)
at VueComponent.Vue._update (node_modules/vue/dist/vue.runtime.common.dev.js:3948:19)
at VueComponent.updateComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4069:10)
at Watcher.get (node_modules/vue/dist/vue.runtime.common.dev.js:4481:25)
at new Watcher (node_modules/vue/dist/vue.runtime.common.dev.js:4470:12)
at mountComponent (node_modules/vue/dist/vue.runtime.common.dev.js:4076:3)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.dev.js:8436:10)
at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:14057:21)
Here's the code for both the test and the component:
ProjectDashboardView.spec.js
import { mount, createLocalVue } from '@vue/test-utils'
import { SERVICES } from '@/utils/common'
import VueRouter from 'vue-router'
import router from '@/router'
import flushPromises from 'flush-promises'
import ProjectDashboardView from '@/components/ProjectDashboard/ProjectDashboardView.vue'
import ProjectDashboardCard from '@/components/ProjectDashboard/ProjectDashboardCard.vue'
jest.mock('@/services/finderService')
const localVue = createLocalVue()
localVue.use(VueRouter)
describe('projectDashboardView', () => {
it('displays ProjectDashboardCards corresponding to all the repositories fetched', async () => {
const wrapper = mount(ProjectDashboardView, {
router,
localVue,
mocks: {
$store: {
state: {
user: {
name: '',
// Array of IDs
repositories: [1, 2],
// Services the user is using to test code quality in their projects
services: SERVICES,
},
},
},
},
})
await flushPromises()
const children = wrapper.findAllComponents(ProjectDashboardCard)
expect(children.length).toBeGreaterThan(0)
})
})
ProjectDashboardView.js
<template>
<v-container class="grid">
<project-dashboard-card
v-for="(value, name) in latestReports"
:key="name"
:repository="value"
/>
<the-add-project-button />
</v-container>
</template>
<script>
import finderService from '@/services/finderService'
import ProjectDashboardCard from '@/components/ProjectDashboard/ProjectDashboardCard'
import TheAddProjectButton from '@/components/ProjectDashboard/TheAddProjectButton'
import { mapState } from 'vuex'
export default {
name: 'ProjectDashboardView',
components: {
ProjectDashboardCard,
TheAddProjectButton,
},
data() {
return {
latestReports: [],
}
},
computed: {
...mapState(['user']),
},
mounted() {
this.fetchLatestReports()
},
methods: {
fetchLatestReports() {
const reportTuples = []
for (const repo of this.user.repositories) {
for (const service of this.user.services) {
reportTuples.push([service, repo])
}
}
const allReports = Promise.all(
reportTuples.map(t => finderService.find(t[0], t[1], true))
)
const latestReports = {}
allReports
.then(responses => {
const filteredResponses = responses.filter(
response => response.data.length > 0
)
filteredResponses.forEach(response => {
if (!latestReports[`repo${response.repoID}`]) {
latestReports[`repo${response.repoID}`] = {}
}
if (!latestReports[`repo${response.repoID}`].repoName) {
latestReports[`repo${response.repoID}`].repoName =
response.data[0].project_name
}
if (!latestReports[`repo${response.repoID}`].services) {
latestReports[`repo${response.repoID}`].services =
{}
}
latestReports[`repo${response.repoID}`].services[
response.service
] = response.data[0]
})
this.latestReports = latestReports
})
.catch(err => console.log(err))
},
},
}
</script>
Just in case, here's the code for the API call mock too:
import sonarqubeReport from './fixtures/find.sonarqube.1.json'
import gitleaksReport from './fixtures/find.gitleaks.1.json'
import dependencycheckReport from './fixtures/find.dependencycheck.1.json'
import hadolintReport from './fixtures/find.hadolint.1.json'
import trivyReport from './fixtures/find.trivy.1.json'
const mockGetResponse = service => {
switch (service) {
case 'sonarqube':
return sonarqubeReport
case 'gitleaks':
return gitleaksReport
case 'dependencycheck':
return dependencycheckReport
case 'hadolint':
return hadolintReport
case 'trivy':
return trivyReport
default:
break
}
}
const finderService = {
find: service => Promise.resolve({ body: mockGetResponse(service) }),
}
export default finderService
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论