Skip to content

常见错误

不能找到模块 './relative-path'

如果你收到一个 module cannot be found 的报错,则可能意味着几种不同情况:

  1. 你拼错了路径。确保路径正确。
  2. 你可能依赖于 tsconfig.json 中的 baseUrl。默认情况下,Vite 不考虑 tsconfig.json,因此如果你依赖此行为,你可能需要自己安装 vite-tsconfig-paths
ts
import tsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vitest/config'

export default defineConfig({
  plugins: [tsconfigPaths()],
})

或者重写你的路径,使它不是相对于 root。

diff
- import helpers from 'src/helpers'
+ import helpers from '../src/helpers'
  1. 确保你没有使用相对路径的 别名。Vite 将它们视为相对于导入所在的文件而不是根目录。
ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    alias: {
      '@/': './src/', 
      '@/': new URL('./src/', import.meta.url).pathname, 
    },
  },
})

Worker 无法终止

当 NodeJS 的 fetchpool: 'threads' 一起使用时,可能会出现此错误。详情请参阅 #3077

默认的 pool: 'forks' 不存在此问题。如果你已显式设置 pool: 'threads',切换回 'forks' 或使用 'vmForks' 即可解决。

自定义包条件无法解析

如果你在 package.jsonexportssubpath imports 中使用了自定义条件,你可能会发现 Vitest 默认不遵循这些条件。

例如,如果你的 package.json 中包含以下内容:

json
{
  "exports": {
    ".": {
      "custom": "./lib/custom.js",
      "import": "./lib/index.js"
    }
  },
  "imports": {
    "#internal": {
      "custom": "./src/internal.js",
      "default": "./lib/internal.js"
    }
  }
}

默认情况下,Vitest 仅使用 importdefault 条件。要让 Vitest 遵循自定义条件,须在 Vitest 配置中配置 ssr.resolve.conditions

vitest.config.js
ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  ssr: {
    resolve: {
      conditions: ['custom', 'import', 'default'],
    },
  },
})

为什么是 ssr.resolve.conditions 而不是 resolve.conditions?

Vitest 遵循 Vite 的配置约定:

  • resolve.conditions 适用于 Vite 的 client 环境,对应 Vitest 的浏览器模式、jsdom、happy-dom,以及使用 viteEnvironment: 'client' 的自定义环境。
  • ssr.resolve.conditions 适用于 Vite 的 ssr 环境,对应 Vitest 的 node 环境或使用 viteEnvironment: 'ssr' 的自定义环境。

由于 Vitest 默认使用 node 环境(该环境使用 viteEnvironment: 'ssr'),模块解析将使用 ssr.resolve.conditions。这同时适用于包导出(package exports)和子路径导入(subpath imports)。

你可以在 environment 中了解更多关于 Vite 环境和 Vitest 环境的内容。

段错误与原生代码错误

运行 原生 NodeJS 模块pool: 'threads' 中,可能会遇到来自原生代码的神秘错误。

  • Segmentation fault (core dumped)
  • thread '<unnamed>' panicked at 'assertion failed
  • Abort trap: 6
  • internal error: entered unreachable code

在这些情况下,原生模块可能不是为多线程安全而构建的。在解决方案中,你可以切换到 pool: 'forks',它在多个 node:child_process 而不是多个 node:worker_threads 中运行测试用例。

ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    pool: 'forks',
  },
})
bash
vitest --pool=forks

Unhandled Promise Rejection

This error happens when a Promise rejects but no .catch() handler or await is attached to it before the microtask queue flushes. This behavior comes from JavaScript itself and is not specific to Vitest. Learn more in the Node.js documentation.

A common cause is calling an async function without awaiting it:

ts
async function fetchUser(id) {
  const res = await fetch(`/api/users/${id}`)
  if (!res.ok) {
    throw new Error(`User ${id} not found`) 
  }
  return res.json()
}

test('fetches user', async () => {
  fetchUser(123) 
})

Because fetchUser() is not awaited, its rejection has no handler and Vitest reports:

Unhandled Rejection: Error: User 123 not found

Fix

await the promise so Vitest can catch the error:

ts
test('fetches user', async () => {
  await fetchUser(123) 
})

If you expect the call to throw, use expect().rejects:

ts
test('rejects for missing user', async () => {
  await expect(fetchUser(123)).rejects.toThrow('User 123 not found')
})