Les tests instantanés dans Jest et Vitest sont des outils puissants pour détecter les changements inattendus dans la sortie de votre code. Cependant, ils se cassent facilement lorsqu'il s'agit de valeurs dynamiques telles que des identifiants générés ou des horodatages qui changent à chaque exécution de test. Bien que se moquer de ces valeurs soit possible, cela peut entraîner des effets secondaires involontaires.
Considérez cet objet utilisateur qui pourrait être renvoyé par un appel API ou une requête de base de données :
const user = { id: crypto.randomUUID(), name: "John Doe", createdAt: new Date().toISOString() };
Chaque fois que vous exécutez vos tests, les valeurs id etcreatedAt seront différentes, provoquant l'échec de vos instantanés.
Voici comment créer un sérialiseur personnalisé qui remplace les valeurs dynamiques par des espaces réservés cohérents :
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, ); }, });
Vous pouvez ajouter un sérialiseur d'instantanés personnalisé avec expect.addSnapshotSerializer().
Il attend un objet avec deux fonctions :
test() est utilisé pour déterminer si ce sérialiseur personnalisé doit être utilisé. Il vérifie si la valeur de expect(value) est un objet avec la propriété et n'a pas été remplacée par l'espace réservé.
serialize() n'est appelé que si test() a renvoyé true. Il remplace la propriété par l'espace réservé et appelle la fonction Printer() pour sérialiser la valeur dans une chaîne de type JSON.
Maintenant, lorsque vous exécuterez vos tests, vous verrez que l'identifiant a été remplacé par l'espace réservé [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", } `); });
Et si nous devons gérer plusieurs propriétés dynamiques ? Créons une solution réutilisable :
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, ); }, }; };
Dans vos tests, vous pouvez créer plusieurs sérialiseurs pour différentes propriétés :
expect.addSnapshotSerializer(replaceProperty('id', '[ID]')); expect.addSnapshotSerializer(replaceProperty('createdAt', '[TIMESTAMP]'));
J'utilise ces sérialiseurs si fréquemment que j'ai créé le package npm snapshot-serializers pour faciliter la tâche de tout le monde.
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... }) );
Il fournit une API de type sécurisé pour remplacer ou supprimer des propriétés dans vos instantanés. Vous pouvez fournir un paramètre de type générique tel que removeProperty
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!