171 votes

Comment simuler une fonction nommée importée dans Jest lorsque le module est débloqué

J'ai le module suivant, je suis en train de tester, en Plaisantant:

// myModule.js

export function otherFn() {
  console.log('do something');
}

export function testFn() {
  otherFn();

  // do other things
}

Comme indiqué ci-dessus, il exportations de certaines fonctions nommées et, surtout, testFn utilise otherFn.

En Plaisantant, quand je suis en train d'écrire mon test unitaire pour testFn, je veux de se moquer de l' otherFn fonction parce que je ne veux pas d'erreurs en otherFn d'affecter 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/insight est apprécié.

183voto

gfullam Points 5129

Utiliser jest.requireActual() à l'intérieur d' jest.mock()

jest.requireActual(moduleName)

Retourne la vraie module à la place d'une maquette, en contournant toutes vérifie si le module doit recevoir un simulacre de mise en œuvre ou non.

Exemple

Je préfère cette concise d'utilisation où vous avez besoin et la propagation à l'intérieur de l' return:

// myModule.test.js

jest.mock('./myModule.js', () => {
  return {
    ...(jest.requireActual('./myModule.js')),
    otherFn: () => {}
  }
})

describe(...)

Cette méthode est également référencé dans la Plaisanterie Manuel se moque de la documentation (près de la fin d' Exemples):

Pour s'assurer qu'un manuel de fantaisie et de sa mise en œuvre réelle séjour dans la synchronisation, il peut être utile d'exiger que le réel module à l'aide de jest.requireActual(moduleName) dans le manuel de votre fantaisie et de le modifier avec des simulations de fonctions avant de les exporter.

47voto

Regarde comme je suis en retard pour cette partie, mais oui, c'est possible.

testFn juste besoin de faire appel otherFn de l'utilisation du module.

Si testFn utilise le module d'appel otherFn alors que le module d'exportation pour otherFn peut être bafoué, testFn qui fera appel à la fantaisie.


Voici un exemple:

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
  });
});

40voto

bobu Points 343
 import m from '../myModule';
 

Ne fonctionne pas pour moi, j'ai utilisé:

 import * as m from '../myModule';

m.otherFn = jest.fn();
 

11voto

vutran Points 633

Le transpiled code ne sera pas permettre à babel pour récupérer la liaison qu' otherFn() fait référence. Si vous utilisez une fonction d'expression, vous devriez être en mesure d'atteindre les moqueries 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 mentionné dans le commentaire précédent, vous avez sans doute ne voulez pas de se moquer otherFn(). Plutôt, il suffit d'écrire une nouvelle spécification pour otherFn() et se moquer de tout le nécessaire appels de décisions.

Ainsi, par exemple, si otherFn() est de faire une requête http...

// myModule.js
exports.otherFn = () => {
  http.get('http://some-api.com', (res) => {
    // handle stuff
  });
};

Ici, vous souhaitez de se moquer http.get et de mettre à jour vos affirmations basées sur votre moqué de mise en œuvre.

// myModule.test.js
jest.mock('http', () => ({
  get: jest.fn(() => {
    console.log('test');
  }),
}));

0voto

Sur le dessus de la première réponse ici, vous pouvez utiliser babel-plugin-rewire pour se moquer importés fonction nommée trop. Vous pouvez consulter la section superficiellement pour fonction nommée recâblage.

L'un des avantages immédiats pour votre situation ici est que vous n'avez pas besoin de changer la façon dont vous appelez de l'autre fonction de votre fonction.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X