Jest 和 Vitest 中的快照測試是偵測程式碼輸出中意外變化的強大工具。然而,在處理動態值(例如產生的 ID 或隨每次測試運行而變化的時間戳記)時,它們很容易崩潰。雖然模擬這些值是可能的,但它可能會導致意想不到的副作用。
考慮可以從 API 呼叫或資料庫查詢傳回的使用者物件:
const user = { id: crypto.randomUUID(), name: "John Doe", createdAt: new Date().toISOString() };
每次執行測試時,id 和createdAt 值都會不同,導致快照失敗。
以下是如何建立一個自訂序列化器,用一致的佔位符取代動態值:
const property = 'id'; const placeholder = '[ID]'; expect.addSnapshotSerializer({ test(val) { return val && typeof val === 'object' && Object.hasOwn(val, property) && val[property] !== placeholder }, serialize(val, config, indentation, depth, refs, printer) { return printer( { ...(val as Record<string, unknown>), [property]: placeholder, }, config, indentation, depth, refs, ); }, });
您可以使用expect.addSnapshotSerializer()新增自訂快照序列化器。
它需要一個具有兩個功能的物件:
test() 用於判斷是否應使用此自訂序列化器。它檢查 Expect(value) 中的值是否是具有該屬性的物件並且未被佔位符替換。
serialize() 只有在 test() 傳回 true 時才會被呼叫。它用佔位符替換屬性,並呼叫 Printer() 函數將值序列化為類似 JSON 的字串。
現在,當您執行測試時,您將看到 id 已替換為 [ID] 佔位符:
interface User { id: string; name: string; createdAt: string; } expect.addSnapshotSerializer({ /* ... */ }); test('snapshot', () => { const user: User = { id: '123e4567-e89b-12d3-a456-426614174000', name: 'John Doe', createdAt: '2024-03-20T12:00:00Z', }; expect(user).toMatchInlineSnapshot(` { "id": "[ID]", "name": "John Doe", } `); });
如果我們需要處理多個動態屬性怎麼辦?讓我們建立一個可重複使用的解決方案:
export const replaceProperty = ( property: string, placeholder: string, ): SnapshotSerializer => { return { test(val) { return val && typeof val === 'object' && Object.hasOwn(val, property) && val[property] !== placeholder }, serialize(val, config, indentation, depth, refs, printer) { return printer( { ...(val as Record<string, unknown>), [property]: placeholder, }, config, indentation, depth, refs, ); }, }; };
在測試中,您可以為不同的屬性建立多個序列化器:
expect.addSnapshotSerializer(replaceProperty('id', '[ID]')); expect.addSnapshotSerializer(replaceProperty('createdAt', '[TIMESTAMP]'));
我經常使用這些序列化器,因此我創建了 npm 套件快照序列化器來讓每個人都更容易使用。
import { replaceProperty, removeProperty } from 'snapshot-serializers'; type User = { id: string; name: string; createdAt: string; password?: string; }; // Type-safe property replacement expect.addSnapshotSerializer( // TypeScript will only allow "id" | "name" | "createdAt" | "password" replaceProperty<User>({ property: 'id', placeholder: '[ID]' }) ); // Remove properties entirely expect.addSnapshotSerializer( removeProperty<User>({ property: 'password' }) ); // This would cause a TypeScript error: expect.addSnapshotSerializer( replaceProperty<User>({ property: 'invalid' // Error: Type '"invalid"' is not assignable... }) );
它提供了類型安全的 API 來替換或刪除快照中的屬性。您可以提供一個通用類型參數,例如removeProperty
以上是如何使用序列化器從快照中刪除動態值的詳細內容。更多資訊請關注PHP中文網其他相關文章!