J'essaie de tester le module suivant dans Jest:
// myModule.js
export function otherFn() {
console.log('do something');
}
export function testFn() {
otherFn();
// do other things
}
Comme indiqué ci-dessus, il exporte certaines fonctions nommées et testFn
utilise otherFn
.
En plaisanterie quand j'écris mon test unitaire pour testFn
, je veux me moquer de la fonction otherFn
car je ne veux pas que les erreurs dans otherFn
affectent mon test unitaire pour testFn
. Mon problème est que je ne suis pas sûr de la meilleure façon de le faire:
// myModule.test.js
jest.unmock('myModule');
import { testFn, otherFn } from 'myModule';
describe('test category', () => {
it('tests something about testFn', () => {
// I want to mock "otherFn" here but can't reassign
// a.k.a. can't do otherFn = jest.fn()
});
});
Toute aide/perspicacité est appréciée.
import m from '../myModule';
Ne fonctionne pas pour moi, j'ai utilisé:
import * as m from '../myModule';
m.otherFn = jest.fn();
Le code transpilé ne permettra pas à babel de récupérer la liaison à laquelle se réfère otherFn()
. Si vous utilisez une expession de fonction, vous devriez pouvoir réaliser otherFn()
.
// myModule.js
exports.otherFn = () => {
console.log('do something');
}
exports.testFn = () => {
exports.otherFn();
// do other things
}
// myModule.test.js
import m from '../myModule';
m.otherFn = jest.fn();
Mais comme @kentcdodds l'a mentionné dans le commentaire précédent, vous ne voudriez probablement pas vous moquer de otherFn()
. Ecrivez plutôt une nouvelle spécification pour otherFn()
et simulez tous les appels nécessaires.
Donc, par exemple, si otherFn()
fait une requête http ...
// myModule.js
exports.otherFn = () => {
http.get('http://some-api.com', (res) => {
// handle stuff
});
};
Ici, vous voudrez simuler http.get
et mettre à jour vos assertions en fonction de vos implémentations simulées.
// myModule.test.js
jest.mock('http', () => ({
get: jest.fn(() => {
console.log('test');
}),
}));
jest.requireActual()
dans __jest.mock()
jest.requireActual(moduleName)
Renvoie le module actuel au lieu d'un simulacre, en ignorant toutes les vérifications pour savoir si le module doit ou non recevoir une implémentation simulée.
Je préfère cet usage concis où vous avez besoin et que vous répandez dans la return
:
// myModule.test.js
jest.mock('./myModule.js', () => {
return {
...(jest.requireActual('./myModule.js')),
otherFn: () => {}
}
})
describe(...)
Cette méthode est également référencée dans la documentation de Jest's Manual Mocks (vers la fin de Exemples ):
Pour vous assurer que la maquette manuelle et sa mise en œuvre réelle restent synchronisées, il peut être utile d'exiger que le module réel utilise
jest.requireActual(moduleName)
dans votre maquette manuelle et qu'il soit modifié avec des fonctions fictives avant de l'exporter.
On dirait que je suis en retard à cette fête, mais oui, c'est possible.
testFn
doit juste appeler otherFn
en utilisant le module .
Si testFn
utilise le module pour appeler otherFn
, l'exportation du module pour otherFn
peut être fausse et testFn
appellera la fausse.
Voici un exemple de travail:
myModule.js
import * as myModule from './myModule'; // import myModule into itself
export function otherFn() {
return 'original value';
}
export function testFn() {
const result = myModule.otherFn(); // call otherFn using the module
// do other things
return result;
}
myModule.test.js
import * as myModule from './myModule';
describe('test category', () => {
it('tests something about testFn', () => {
const mock = jest.spyOn(myModule, 'otherFn'); // spy on otherFn
mock.mockReturnValue('mocked value'); // mock the return value
expect(myModule.testFn()).toBe('mocked value'); // SUCCESS
mock.mockRestore(); // restore otherFn
});
});
En plus de la première réponse, vous pouvez utiliser babel-plugin-rewire pour simuler une fonction nommée importée. Vous pouvez consulter la section superficiellement pour fonction nommée recâblage .
L’un des avantages immédiats de votre situation est qu’il n’est pas nécessaire de modifier la façon dont vous appelez l’autre fonction de votre fonction.