Aller au contenu
Mocking de la date actuelle dans les tests de Jest
  1. Blogs/

Mocking de la date actuelle dans les tests de Jest

·530 mots·3 mins·

Il y a des situations où new Date() ou Date.now est utilisée dans le code de l’application. Ce code doit être testé, et il est toujours difficile de se rappeler comment le moquer.

L’utilisation de Date.now vs new Date()
#

Date.now() retourne le temps au format unix, c’est à dire “le nombre de millisecondes écoulées depuis le 1er janvier 1970 00:00:00 UTC”. (voir Date.now sur MDN).

new Date() retourne un nouvel objet Date, et se comporte différemment en fonction de l’entrée qui lui est passée. S’il est appelé sans rien, il retourne la date actuelle.

Les valeurs suivantes sont équivalentes, bien que les valeurs stockées dans les deux variables soient strictement différentes.

const now = new Date();
const explicitNow = new Date(Date.now());

Les valeurs sont strictement différentes parce que le “now” est calculé à des moments différents, mais comme le constructeur Date (new Date()) supporte le passage d’un temps unix à celui-ci, les deux sont équivalents.

L’utilisation de la new Date(Date.now()) rend le code beaucoup plus facile à tester. Mocker une fonction qui retourne un nombre (comme Date.now) est beaucoup plus facile que se moquer d’un constructeur.

Par exemple, le code complet du paquet jest-mock-now est le suivant (voir le code sur github.com/mattiaerre/jest-mock-now) :

const { NOW } = require('./constants');

module.exports = date => {
  const now = date ? date.getTime() : NOW;
  Date.now = jest.spyOn(Date, 'now').mockImplementation(() => now);
  return now;
};

Remplacer Date.now par un substitut
#

const literallyJustDateNow = () => Date.now();

test('It should call and return Date.now()', () => {
  const realDateNow = Date.now.bind(global.Date);
  const dateNowStub = jest.fn(() => 1530518207007);
  global.Date.now = dateNowStub;

  expect(literallyJustDateNow()).toBe(1530518207007);
  expect(dateNowStub).toHaveBeenCalled();

  global.Date.now = realDateNow;
});

Ce n’est pas vraiment une astuce spécifique à Jest, nous accédons simplement à l’objet global de Node et remplaçons Date.now par un stub.

Espionnez Date.now et ajoutez une implémentation fictive
#

Une implémentation simplifiée d’un test similaire serait d’utiliser jest.spyOn(global.Date,'now').mockImplementation().

Notre implémentation du mock utilisera une date codée en dur initialisée à l’aide de la new Date('valid-date-string') et return valueOf(), qui correspond à l’heure unix de cette date.

const getNow = () => new Date(Date.now());

test('It should create correct now Date', () => {
  jest
    .spyOn(global.Date, 'now')
    .mockImplementationOnce(() =>
      new Date('2019-08-24T11:01:58.135Z').valueOf()
    );

  expect(getNow()).toEqual(new Date('2019-08-24T11:01:58.135Z'));
});

Cela a l’avantage de ne pas avoir à remplacer la date réelle ou à la remettre à plus tard.

Mocker toute la classe Date avec une instance à date fixe
#

const getCurrentDate = () => new Date();
let realDate;

test('It should create new date', () => {
  // Setup
  const currentDate = new Date('2019-08-24T11:01:58.135Z');
  realDate = Date;
  global.Date = class extends Date {
    constructor(date) {
      if (date) {
        return super(date);
      }

      return currentDate;
    }
  };

  expect(getCurrentDate()).toEqual(new Date('2019-08-24T11:01:58.135Z'));

  // Cleanup
  global.Date = realDate;
});

Source Github: “Mocking current time for Date”

Comme nous l’avons mentionné dans l’introduction, se moquer de toute la classe est très brutal.

Espionnez le nouveau constructeur Date() et ajoutez une implémentation fictive
#

const getCurrentDate = () => new Date();
test('It should create new date', () => {
  jest
    .spyOn(global, 'Date')
    .mockImplementationOnce(() => new Date('2019-08-24T11:01:58.135Z'));

  expect(getCurrentDate()).toEqual(new Date('2019-08-24T11:01:58.135Z'));
});

C’est joli et concis, mais repose sur JavaScript hisser la folie et de savoir que Jest vous permet de simuler global.date.

Articles connexes

Jest ignore ou exclure le fichier/fonction/état de la couverture de test
·882 mots·5 mins
Cet article explique comment ignorer les fichiers, fonctions, lignes et déclarations de la couverture dans Jest en utilisant la configuration ou istanbul pragmas. Ainsi que les raisons et les limites du pourquoi/comment vous feriez une telle chose.
Prise en main de PM2, le gestionnaire de processus Node.js
·584 mots·3 mins
Utilisations de PM2 # PM2 a beaucoup d’utilisations, jetons un coup d’oeil à quelques-unes d’entre elles: Redémarrage après un crash: PM2 nous permet de maintenir les processus en cours d’exécution Suivi et gestion des processus à distance: un portail web vous permet de garder un oeil sur les precessus distants et de les gérer.
Premiers pas avec LoopBack 4
·1576 mots·8 mins
LoopBack 4 est un framework d’API open-source. La dernière version a adopté les dernières fonctionnalités de ES2016/2017/2018, supporte TypeScript et intègre de nouveaux standards tels que OpenAPI Spec et GraphQL, parmi d’autres.