J'ai du code qui fait quelque chose comme
function myFunc(condition){
if(condition){
process.exit(ERROR_CODE)
}
}
Comment puis-je tester cela dans Jest? Écraser exit
dans process
avec jest.fn()
et le renvoyer après le test ne fonctionne pas, car le processus se termine
Les autres suggestions de ce fil entraîneraient des erreurs de ma part, où tous les tests avec process.exit
S'exécuteraient indéfiniment. L'option suivante a fonctionné pour moi sur TypeScript, mais elle devrait également fonctionner sur JavaScript:
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
myFunc(condition);
expect(mockExit).toHaveBeenCalledWith(ERROR_CODE);
Le hic est que le simple fait d'utiliser spyOn
signifiait que la fonction process.exit()
d'origine était toujours appelée, mettant fin au thread de processus et suspendant les tests. L'utilisation de mockImplementation
à la fin remplace le corps de la fonction par la fonction fournie (qui est vide dans mon exemple).
Cette astuce est également utile pour les tests qui s'impriment sur, disons, stdout. Par exemple:
const println = (text: string) => { process.stdout.write(text + '\n'); };
const mockStdout = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});
println('This is a text.');
expect(mockStdout).toHaveBeenCalledWith('This is a text.\n');
Cela vous permettra de tester les valeurs imprimées et aura l'avantage supplémentaire de ne pas gâcher la sortie de la console CLI avec des sauts de ligne aléatoires.
Une seule remarque: comme pour tout appel "jest.spyOn", que vous utilisiez ou non une implémentation fictive, vous devez la restaurer plus tard afin d'éviter les effets secondaires étranges des mockings persistants. N'oubliez donc pas d'appeler les deux fonctions suivantes à la fin du scénario de test actuel:
mockExit.mockRestore()
mockStdout.mockRestore()
Pour la plupart de l'objet javascript global, j'essaie de le remplacer par mon stub et de le restaurer après le test. La suite fonctionne bien pour moi de se moquer de process
.
describe('myFunc', () => {
it('should exit process on condition match', () => {
const realProcess = process;
const exitMock = jest.fn();
// We assign all properties of the "real process" to
// our "mock" process, otherwise, if "myFunc" relied
// on any of such properties (i.e `process.env.NODE_ENV`)
// it would crash with an error like:
// `TypeError: Cannot read property 'NODE_ENV' of undefined`.
global.process = { ...realProcess, exit: exitMock };
myFunc(true);
expect(exitMock).toHaveBeenCalledWith(ERROR_CODE);
global.process = realProcess;
});
});
Cela permet d'éviter d'exécuter le vrai process.exit
pour éviter de planter le test unitaire.
Vous pouvez utiliser jest.spyOn
car cela appellera également la méthode d'origine:
const exit = jest.spyOn(process, 'exit');
//run your test
expect(exit).toHaveBeenCalledWith('ERROR_CODE');
J'ai fait face à un problème similaire. Résolu avec le code ci-dessous
const setProperty = (object, property, value) => {
const originalProperty = Object.getOwnPropertyDescriptor(object, property)
Object.defineProperty(object, property, { value })
return originalProperty
}
const mockExit = jest.fn()
setProperty(process, 'exit', mockExit)
expect(mockExit).toHaveBeenCalledWith('ERROR_CODE')