web-dev-qa-db-fra.com

Se moquer d'une fonction de classe ES6 avec Jest

J'ai une question sur la façon dont je peux me moquer d'une instance de classe ES6 en utilisant Jest qui est utilisé par la méthode que je veux réellement tester. Mon cas réel essaie de tester un créateur d'action asynchrone Redux qui fait une demande et envoie une action en fonction du résultat de la demande.

Voici un exemple simplifié du cas d'utilisation:

// communication.js
// An exported ES6 class module with proxy to the request library.
import post from './post';
export default class communication {

    getData(data, success, error) {
        const res = post(data);
        if(res) {
            success();
        } else {
            error();
        }
    }
}

// communicatorAssist.js
// A redux async function using communication.js
import communication from './communication';
// ...

export function retrieveData() {
    return dispatch => {
        const data = { name: 'michel'};
        communication.getData(data,
            (res) => dispatch(successAction(res)),
            (res) => dispatch(errorAction(res));
    }
}

// communicatorAssist.test.js testing the communicatorAssist
import { retrieveData } from 'communicatorAssist';

// communication.getData should call success callback
// for this test.
it('Should call the success callback', () => {
    retrieveData();
    // Assert that mocked redux store contains actions
});

// communication.getData should call error callback
// for this test.
it('Should call the error callback', () => {
    retrieveData();
    // Assert that mocked redux store contains actions
});

Ce que je veux, c'est se moquer de la classe de communication dans le test et changer le comportement de la fonction getData() dans chaque test pour appeler des rappels success et error sans aucune méthode call to post .

J'ai réussi à simuler la fonction getData() pour tout le fichier de test avec cet extrait en haut:

import communication from '../communication'
jest.mock('../communication', () => (() => ({
    getData: (success, error) => success()
})));

mais je ne peux pas basculer entre l'implémentation dans différents cas de test.

Je pense que quelque chose utilisant .mockImplementation() pourrait faire les choses mais je ne peux pas faire fonctionner cela dans mon cas (j'ai vu des exemples l'utilisant pour les fonctions d'exportation de module mais pas pour les classes).

Est-ce que quelqu'un a une idée ?

Modifier:

J'ai oublié une partie dans l'exemple de code: la création d'instance de classe de communication qui je pense est le "problème" pour se moquer d'elle:

const com = new communication();

Si com est instancié à un niveau global dans le fichier communicatorAssist.js: il échoue avec communication.getData n'est pas une erreur de fonction .

Mais si je mets l'instanciation à l'intérieur de la fonction retrieveData(), Andreas Köberle fonctionne correctement:

import communication from '../communication'
jest.mock('../communication', () => jest.fn());

communication.mockImplementation(
  () => ({
    getData: (success, error) => success()
  })
)

(jest.mock() le paramètre d'usine doit renvoyer une fonction non directement jest.fn)

Je ne sais pas pourquoi cela ne fonctionne pas en utilisant une instance de portée globale de fichier.

10
Imk

Vous devez vous moquer du module avec jest.fn() puis vous pouvez l'importer et changer son comportement en utilisant mockImplementation :

import communication from '../communication'
jest.mock('../communication', jest.fn());

communication.mockImplementation(
  () => ({
    getData: (success, error) => success()
  })
)
11
Andreas Köberle

Si vous souhaitez renvoyer le résultat à un appel de fonction sur un UsedClass.

import UsedClass from './usedClassPath'

jest.mock('./usedClassPath');

test("some test", () => {
  const usedClassMockInstance = new UsedClass();

//mock implementation here
  usedClassMockInstance.usedClassMethod = jest.fn().mockImplementation(async () => {
    return returnValueYourMethodMightReturn;
  });

//your test here

})

maintenant le UsedClass est moqué et le userClassMethod retourne quelque chose que vous attendez qu'il retourne ie., returnValueYourMethodMightReturn

0
Jknair