Maison >interface Web >js tutoriel >Se moquer avec Jest et dactylographié - une aide-mémoire

Se moquer avec Jest et dactylographié - une aide-mémoire

Barbara Streisand
Barbara Streisandoriginal
2024-12-22 22:31:11609parcourir

Mocking with Jest and typescript - a cheatsheet

Jest est excellent pour se moquer des importations en javascript/typescript, mais j'ai beaucoup de mal à me souvenir des détails de l'implémentation.

Les fonctions et les objets doivent être simulés de différentes manières, les exportations par défaut sont simulées de manière subtilement différente des exportations nommées, et Jest ne fonctionne pas particulièrement bien avec TypeScript. Combinez toutes ces choses et il peut être difficile d'élaborer, ou même de rechercher, la bonne approche pour votre scénario moqueur.

J'ai créé ce guide pour répondre à la question "Comment puis-je me moquer de mon importation ?" quelle que soit cette importation. Par défaut ou nommé, fonction ou objet.

Mon environnement

J'ai testé toutes ces approches en utilisant les versions de logiciels suivantes :

  • nœud v22.11.0
  • blague v29.7.0
  • ts-jest v29.2.5
  • @types/jest v29.5.14

Et avec un fichier jest.config.js minimal par défaut :

export default {
  testEnvironment: 'node',
  transform: {
    '^.+.tsx?$': ['ts-jest', {}],
  },
  testMatch: ['**/*.test.ts'],
};

Importations moqueuses

Les importations largement courantes se répartissent en deux catégories dont nous pourrions vouloir nous moquer :

  • fonctions
  • objets

Nous les aborderons tour à tour, en commençant par les fonctions.

Fonctions d'importation

Les fonctions exportées à partir des modules peuvent être nommées ou par défaut. Nous examinerons les deux. Premièrement :

Se moquer d'une fonction exportée nommée à partir d'un module

Cela devrait être utilisé pour simuler une fonction exportée nommée à partir d'un module, quelque chose comme ceci :

// ./path/to/module.ts

export function doSomething(...) {
  ...
}

On peut se moquer de cette façon :

import { doSomething } from './path/to/module';

// note: This should be the path to the module from the test file,
// NOT from the module that contains the doSomething function itself.
jest.mock('./path/to/module', () => ({
  doSomething: jest.fn(),
}));

...

it('should do something', () => {
  // We need to assert that the function is a jest.Mock
  // so that typescript will allow us to call mock methods.
  (doSomething as jest.Mock).mockReturnValue(mockValue);

  // run your test here

  expect(doSomething).toHaveBeenCalledTimes(1); // etc.
});

Se moquer de la fonction par défaut renvoyée par un module

Cela devrait être utilisé pour simuler une fonction qui est l'exportation par défaut d'un module, quelque chose comme ceci :

// ./path/to/module.ts

export default function doSomething(...) {
  ...
}

Il est moqué de la même manière que les exportations nommées :

import doSomething from './path/to/module'

jest.mock('./path/to/module', () => ({
  __esModule: true,
  default: jest.fn()
}))

...

it('should do something', () => {
  (doSomething as jest.Mock).mockResolvedValue(mockData);

  // Run your test here

  expect(doSomething).toHaveBeenCalledTimes(5);
});

Importer des objets

Il existe quelques variantes à prendre en compte lors de la simulation d'un objet exporté (qu'il s'agisse d'une classe, d'un objet json ou autre).

  • Est-ce une exportation nommée ou par défaut ?
  • A-t-il des méthodes dont nous souhaitons également nous moquer, ou simplement des propriétés ?

Se moquer des objets par défaut sans méthodes

Si vous avez juste besoin de vous moquer de propriétés (un fichier de configuration par exemple), pas de méthodes, alors voici comment procéder :

import config from '../config';

jest.mock('../config', () => ({
  __esModule: true,
  default: {
    apiKey: '123MockKey',
    ...
  },
}));

...

it('Should do something', () => {
  ...
});

Et si les propriétés simulées doivent varier selon le test :

import config from '../config';

const mockConfig = {
  apiKey: '123MockKey',
  ...
};

jest.mock('../config', () => ({
  __esModule: true,
  default: mockConfig,
}));

...

beforeEach(() => {
  // restore defaults before each test
  mockConfig.apiKey = '123MockKey';
  ...
});

it('Should do something', () => {
  mockConfig.apiKey = 'new value';

  // rest of the test
});

// more tests

Se moquer des objets d'exportation nommés sans méthodes

Très similaire aux objets d'exportation par défaut moqueurs :

import { config } from '../config';

const mockConfig = {
  apiKey: '123MockKey',
  ...
};

jest.mock('../config', () => ({
  config: mockConfig,
}));

// the rest is exactly the same as when mocking a default export object.

Se moquer d'un objet avec des méthodes

Lorsqu'un objet avec des méthodes est exporté (nommé ou par défaut) à partir d'un module et que nous devons nous moquer de la sortie de ces méthodes, l'approche est légèrement différente.

Étant donné un cours :

// ./path/to/module.ts

class ComplicatedThing {
  // properties, fields, constructor etc. go here

  getData() {
    ...
  }

  ...
}

// note: I don't necessarily recommend exporting an instance
// of a class like this - purely illustrative for testing purposes.
// https://medium.com/@lazlojuly/are-node-js-modules-singletons-764ae97519af
export const complicatedThing = new ComplicatedThing(...);

Et pour se moquer de notre objet exporté :

export default {
  testEnvironment: 'node',
  transform: {
    '^.+.tsx?$': ['ts-jest', {}],
  },
  testMatch: ['**/*.test.ts'],
};

Se moquer d'un objet d'export par défaut est exactement la même chose sauf lorsque nous définissons le mock :

// ./path/to/module.ts

export function doSomething(...) {
  ...
}

Bonus : Méthodes moqueuses sur un objet passé directement à une fonction/classe de test en paramètre

C'est pour se moquer d'un objet qui n'est pas directement importé dans un module que vous testez, mais qui est plutôt transmis en tant que paramètre à une classe/fonction.

Remarque : Si vous vous moquez d'une classe, vous souhaiterez peut-être plutôt créer une interface et créer une implémentation simulée de celle-ci à transmettre à votre fonction/classe. Cela vous évitera d'avoir à faire des manigances d'affirmation de type inélégantes comme ci-dessous.

import { doSomething } from './path/to/module';

// note: This should be the path to the module from the test file,
// NOT from the module that contains the doSomething function itself.
jest.mock('./path/to/module', () => ({
  doSomething: jest.fn(),
}));

...

it('should do something', () => {
  // We need to assert that the function is a jest.Mock
  // so that typescript will allow us to call mock methods.
  (doSomething as jest.Mock).mockReturnValue(mockValue);

  // run your test here

  expect(doSomething).toHaveBeenCalledTimes(1); // etc.
});
// ./path/to/module.ts

export default function doSomething(...) {
  ...
}
import doSomething from './path/to/module'

jest.mock('./path/to/module', () => ({
  __esModule: true,
  default: jest.fn()
}))

...

it('should do something', () => {
  (doSomething as jest.Mock).mockResolvedValue(mockData);

  // Run your test here

  expect(doSomething).toHaveBeenCalledTimes(5);
});

Conclusion

J'espère que cela vous sera utile, ainsi qu'à moi-même, la prochaine fois que j'aurai du mal à me souvenir des détails sur la façon de se moquer des importations en dactylographié.

J'espère qu'il pourra couvrir tous vos besoins de moquerie simples et vous donner un point de départ pour vous moquer d'importations plus complexes.

Merci d'avoir lu.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn