Mocker les méthodes des interfaces par spyOn
06 juin 2023
TL;DR
Mocker les méthodes des interfaces par spyOn (exemple : jest.spyOn(httpClientService, 'get').mockResolvedValue(...)
)
Contributeurs
Suxue Li, Julie Brunetto, Guillaume Moizan, Gauthier Fiorentino, Dorian De Rosa, Fred Nobre
Statut
Accepté
Contexte
Plusieurs manières de mocker / stubber une dépendance, exemple avec la méthode get
sur le httpClientService
:
(httpClientService.get as jest.Mock).mockResolvedValue(...)
jest.spyOn(httpClientService, 'get').mockResolvedValue(...)
anHttpClientService({ get: jest.fn(async () => ({...}) })
Après discussion, l'équipe s'accorde sur :
(httpClientService.get as jest.Mock).mockResolvedValue(...)
-> Ne plus le faire car plus besoin de redéfinir manuellement le type
L'équipe est divisée entre le jest.spyOn
et l'override à l'instanciation de la classe, pour des raisons de préférences subjectives de lecture.
En utilisation, la méthode l'override à l'instanciation de la classe (anHttpClientService({ get: jest.fn(async () => ({...}) })
) présente un défaut : lorsqu'on veut mocker la même méthode pour plusieurs appels, par exemple deux appels, on est obligé d'écrire :
const errorManagementService = anErrorManagementService({
handleFailureError: jest.fn(() => createFailure(ErreurMétier.SERVICE_INDISPONIBLE))
.mockImplementationOnce(() => createFailure(ErreurMétier.DEMANDE_INCORRECTE))
.mockImplementationOnce(() => createFailure(ErreurMétier.CONTENU_INDISPONIBLE),
});
De plus, cette méthode présente l'inconvénient de ne pas pouvoir retourner un type union comme Either (Failure | Success) que nous utilisons beaucoup dans le projet. Le type étant inféré de l'implémentation qu'on donne au jest.fn, si cette implémentation retourne une Failure comme l'exemple ci-dessus, .mockImplementationOnce(() => createSuccess({...})
ne sera pas accepté.
Nous ne voulons pas mélanger deux méthodes de mock.
Décision
Pour éviter d'avoir deux manières de faire, la préférence est donnée à la méthode :
jest.spyOn(httpClientService, 'get').mockResolvedValue(...)
(= instancier la fixture de l'interface, et faire un spyOn dessus pour chaque mock qu'on veut mettre en place)
L'équipe s'accorde aussi sur le fait de ne pas initialiser des méthodes / valeurs testées dans un beforeEach
pour garder des tests
autoportants.
Conséquences
Les :
(httpClientService.get as jest.Mock).mockResolvedValue(...)
anHttpClientService({ get: jest.fn(async () => ({...}) })
et équivalent sur autres interfaces / méthodes sont dépréciés