web-dev-qa-db-fra.com

Mock une interface TypeScript avec plaisanterie

Est-il possible de se moquer d'une interface TypeScript avec jest?

Par exemple:

import { IMultiplier } from "./IMultiplier";

export class Math {
  multiplier: IMultiplier;

  public multiply (a: number, b: number) {
    return this.multiplier.multiply(a, b);
  }
}

Puis dans un test:

import { Math } from "../src/Math";
import { IMultiplier } from "../src/IMultiplier";

describe("Math", () => {

    it("can multiply", () => {
        let mathlib = new Math();
        mathlib.multiplier = // <--- assign this property a mock
        let result = mathlib.multiply(10, 2);
        expect(result).toEqual(20);
    });
});

J'ai essayé de créer un objet fictif pour satisfaire cela de plusieurs façons, mais aucune ne fonctionne. Par exemple en lui assignant cette maquette:

let multiplierMock = jest.fn(() => ({ multiply: jest.fn() }));

Produira quelque chose comme:

Error - Type 'Mock<{ multiply: Mock<{}>; }>' is not assignable to type 'IMultiplier'.
3
Cuthbert

La maquette doit simplement avoir le même shape que l'interface.

(à partir de docs : L’un des principes fondamentaux de TypeScript est que la vérification du type est centrée sur la forme des valeurs. C’est parfois appelé «typage de canard» ou «sous-typage structural».)

Donc, mathlib.multiplier doit simplement être affecté à un objet conforme à IMultiplier.

Je suppose que IMultiplier de l'exemple ressemble à ceci:

interface IMultiplier {
  multiply(a: number, b: number): number
}

Ainsi, l'exemple de test fonctionnera correctement en modifiant la ligne en question comme suit:

mathlib.multiplier = {
  multiply: jest.fn((a, b) => a * b)
};
1