測試環境
Vitest 提供 environment
選項,用於在特定環境中執行程式碼。您可以使用 environmentOptions
選項調整環境行為。
預設情況下,您可以使用以下環境:
node
為預設環境。jsdom
透過jsdom
套件模擬瀏覽器環境,提供瀏覽器 API。happy-dom
透過happy-dom
套件模擬瀏覽器環境,據稱比jsdom
更快速,但缺少部分 API。edge-runtime
模擬 Vercel 的 edge-runtime,使用@edge-runtime/vm
套件。
INFO
當使用 jsdom
或 happy-dom
環境時,Vitest 遵循 Vite 匯入 CSS 和 資產 的相同規則。若匯入外部依賴項失敗並出現 unknown extension .css
錯誤,您需要手動將所有相關套件新增至 server.deps.external
,以確保整個匯入鏈被內聯處理。例如,若錯誤發生在 source code -> package-1 -> package-2 -> package-3
這條匯入鏈中的 package-3
,您需要將 package-1
、package-2
和 package-3
都新增至 server.deps.external
。
自 Vitest 2.0.4 起,外部依賴項中的 CSS 和資產 require
將自動解析。
特定檔案的環境
當您在設定中配置 environment
選項時,它將套用於專案中的所有測試檔案。為實現更精細的控制,您可以使用控制註解為特定檔案指定環境。控制註解以 @vitest-environment
開頭,後接環境名稱:
// @vitest-environment jsdom
import { expect, test } from 'vitest';
test('test', () => {
expect(typeof window).not.toBe('undefined');
});
或者,您也可以設定 environmentMatchGlobs
選項,依據 glob 模式指定環境。
自訂環境
您可以建立自己的套件以擴展 Vitest 環境。為此,請建立名稱為 vitest-environment-${name}
的套件,或指定有效的 JS/TS 檔案路徑。該套件應匯出一個符合 Environment
介面定義的物件:
import type { Environment } from 'vitest';
export default <Environment>{
name: 'custom',
transformMode: 'ssr',
// 選用 - 僅當您支援 "experimental-vm" 執行緒集區時
async setupVM() {
const vm = await import('node:vm');
const context = vm.createContext();
return {
getVmContext() {
return context;
},
teardown() {
// 在所有使用此環境的測試執行完畢後呼叫
},
};
},
setup() {
// 自訂配置
return {
teardown() {
// 在所有使用此環境的測試執行完畢後呼叫
},
};
},
};
WARNING
Vitest 要求環境物件上必須有 transformMode
選項。其值應為 ssr
或 web
。此值決定插件如何轉換原始碼。若設定為 ssr
,插件鉤子在轉換或解析檔案時將收到 ssr: true
。否則,ssr
將設定為 false
。
您也可以透過 vitest/environments
入口存取預設的 Vitest 環境:
import { builtinEnvironments, populateGlobal } from 'vitest/environments';
console.log(builtinEnvironments); // { jsdom, happy-dom, node, edge-runtime }
Vitest 還提供了 populateGlobal
工具函式,可用於將物件的屬性移動至全域命名空間:
interface PopulateOptions {
// 非類別函式是否應綁定至全域命名空間
bindFunctions?: boolean;
}
interface PopulateResult {
// 已複製的所有鍵列表,即使原始物件上不存在該值
keys: Set<string>;
// 原始物件的對應,可能已被鍵覆蓋
// 您可以在 `teardown` 函式中返回這些值
originals: Map<string | symbol, any>;
}
export function populateGlobal(
global: any,
original: any,
options: PopulateOptions
): PopulateResult;