Vitest错误“TypeError:无法读取未定义的属性(读取'resolve')”(router.resolve)

Leo*_*ban 7 javascript unit-testing vuejs3 vitest

我有一个非常基本的测试,但是当我尝试安装组件时它会抛出以下错误const wrapper = mount(HomeHeader)。我已经粘贴了我的 vite 配置、测试、组件和包。

\n

这个错误是在没有更新我的 vite 配置的情况下发生的,但我继续更新了配置,test: { globals: true, }所以我不必导入testexpect.

\n

完全错误

\n
stderr | src/components/home/__tests__/HomeHeader.test.js > HomeHeader renders properly\n[Vue warn]: injection "Symbol([vue-router]: router)" not found.\n  at <RouterLink to="/" >\n  at <HomeHeader ref="VTU_COMPONENT" >\n  at <VTUROOT>\n[Vue warn]: injection "Symbol([vue-router]: route location)" not found.\n  at <RouterLink to="/" >\n  at <HomeHeader ref="VTU_COMPONENT" >\n  at <VTUROOT>\n[Vue warn]: Unhandled error during execution of setup function\n  at <RouterLink to="/" >\n  at <HomeHeader ref="VTU_COMPONENT" >\n  at <VTUROOT>\n\nFAIL  src/components/home/__tests__/HomeHeader.spec.js > HomeHeader > renders properly\nTypeError: Cannot read properties of undefined (reading \'resolve\')\n \xe2\x9d\xaf ReactiveEffect.fn node_modules/vue-router/dist/vue-router.cjs.js:2068:45\n    2066|     const router = vue.inject(routerKey);\n    2067|     const currentRoute = vue.inject(routeLocationKey);\n    2068|     const route = vue.computed(() => router.resolve(vue.unref(props.to)));\n       |                                             ^\n
Run Code Online (Sandbox Code Playgroud)\n

维测试界面

\n

在此输入图像描述

\n

维特配置

\n
import { fileURLToPath, URL } from \'url\'\nimport { defineConfig } from \'vite\'\nimport vue from \'@vitejs/plugin-vue\'\nimport vueJsx from \'@vitejs/plugin-vue-jsx\'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  test: {\n    globals: true,\n  },\n  plugins: [vue(), vueJsx()],\n  resolve: {\n    alias: {\n      \'@\': fileURLToPath(new URL(\'./src\', import.meta.url)),\n    },\n  },\n})\n
Run Code Online (Sandbox Code Playgroud)\n

我的测试

\n
import { mount } from \'@vue/test-utils\'\nimport HomeHeader from \'../HomeHeader.vue\'\n\ndescribe(\'HomeHeader\', () => {\n  it(\'renders properly\', () => {\n    // This breaks\n    const wrapper = mount(HomeHeader)\n    expect(wrapper.text()).toContain(\'MOONHOLDINGS.XYZ\')\n  })\n})\n
Run Code Online (Sandbox Code Playgroud)\n

被测试的组件

\n
<script setup>\nimport { RouterLink } from \'vue-router\'\nimport {\n  MOON_XYZ,\n  LOGIN,\n  LOGIN_PATH,\n  GET_STARTED,\n  SIGN_UP_PATH,\n} from \'../../constants\'\nimport PrimaryBtn from \'@/components/partials/PrimaryBtn.vue\'\n</script>\n\n<template>\n  <main>\n    <header>\n      <h1>\n        <RouterLink to="/">\n          {{ MOON_XYZ }}\n        </RouterLink>\n      </h1>\n      <nav>\n        <RouterLink :to="LOGIN_PATH">{{ LOGIN }}</RouterLink>\n        <PrimaryBtn :copy="GET_STARTED" :url="SIGN_UP_PATH" />\n      </nav>\n    </header>\n  </main>\n</template>\n\n<style lang="scss" scoped>\nh1 {\n  margin: 1em;\n  font-size: 1.375rem;\n  color: #fff;\n}\n\na {\n  color: #fff;\n  text-decoration: none;\n}\n\nnav {\n  position: absolute;\n  right: 2em;\n\n  a {\n    display: inline-block;\n    padding: 0 1rem;\n    font-size: 2em;\n    text-decoration: none;\n    color: #fff;\n    transition: 0.4s;\n\n    .router-link-exact-active {\n      color: #fff;\n    }\n\n    .router-link-exact-active:hover {\n      background-color: transparent;\n    }\n\n    &:hover {\n      text-decoration: underline;\n    }\n\n    &:first-of-type {\n      border: 0;\n    }\n  }\n}\n\n@media (min-width: 1024px) {\n  header {\n    display: flex;\n    place-items: center;\n    padding-right: calc(var(--section-gap) / 2);\n  }\n}\n</style>\n
Run Code Online (Sandbox Code Playgroud)\n

脚本命令"coverage": "vitest run --coverage",

\n

我的依赖

\n
"dependencies": {\n  "animate.css": "^4.1.1",\n  "axios": "^0.27.2",\n  "pinia": "^2.0.14",\n  "vue": "^3.2.36",\n  "vue-router": "^4.0.15"\n},\n"devDependencies": {\n  "@rushstack/eslint-patch": "^1.1.0",\n  "@vitejs/plugin-vue": "^2.3.3",\n  "@vitejs/plugin-vue-jsx": "^1.3.10",\n  "@vitest/ui": "^0.20.3",\n  "@vue/eslint-config-prettier": "^7.0.0",\n  "@vue/test-utils": "^2.0.2",\n  "c8": "^7.11.3",\n  "eslint": "^8.5.0",\n  "eslint-plugin-vue": "^9.0.0",\n  "happy-dom": "^6.0.4",\n  "jsdom": "^19.0.0",\n  "npm-run-all": "^4.1.5",\n  "prettier": "^2.5.1",\n  "ramda": "^0.28.0",\n  "sass": "^1.53.0",\n  "start-server-and-test": "^1.14.0",\n  "vite": "^2.9.9",\n  "vitest": "^0.20.3",\n  "vue-tsc": "^0.35.2"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

有人在使用 Vitest 时遇到过这个问题吗?

\n

在此输入图像描述

\n

Met*_*lmi 4

Vue Router 会被自动模拟,因此无法从中调用任何方法。这就是您在调用时遇到错误的原因resolve()

正确的测试应该是这样的:

import { vi } from 'vitest';
import { mount } from '@vue/test-utils'
import HomeHeader from '../HomeHeader.vue'

// you need to mock router
vi.mock('vue-router', () => ({
  resolve: vi.fn(),
}));

describe('HomeHeader', () => {
  it('renders properly', () => {
    const wrapper = mount(HomeHeader)
    expect(wrapper.text()).toContain('MOONHOLDINGS.XYZ')
  })
})
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!我可以在几个小时内奖励,修复了当前的错误。现在我在子组件内的按钮上收到“TypeError: useRouter is not a function”,这可能不得不最终使用 Jest,直到 Vitest 改进。 (2认同)
  • 啊,这样的话,玩笑似乎就不再那么糟糕了。 (2认同)