60 votes

Comment utiliser Jest pour espionner l'appel d'une méthode ?

J'ai récemment voulu tester qu'une méthode personnalisée est appelée de manière conditionnelle dans le fichier componentDidMount d'un composant React.

componentDidMount() {
  if (this.props.initOpen) {
    this.methodName();
  }
}

J'utilise Jest comme cadre de test, ce qui inclut jest.fn() pour les mocks/spies. J'ai lu que cela serait assez trivial à tester avec Sinon, en faisant quelque chose comme ce qui suit :

sinon.spy(Component.prototype, "methodName");
const wrapper = mount(<Component {...props} />);
expect(wrapper.instance().methodName).toHaveBeenCalled();

J'essaie de recréer cela avec Jest de la manière suivante :

Component.prototype.methodName = jest.fn();
const wrapper = mount(<Component {...props} />);
expect(wrapper.instance().methodName).toHaveBeenCalled();

Ce code échoue et génère l'erreur suivante :

jest.fn() value must be a mock function or spy.
Received:
  function: [Function bound mockConstructor]

Est-il possible de tester cette fonctionnalité avec Jest ? Et si oui, comment ?

106voto

Jonathan Points 725

La clé est l'utilisation de jests spyOn de l'objet prototype . Ça devrait être comme ça :

const spy = jest.spyOn(Component.prototype, 'methodName');
const wrapper = mount(<Component {...props} />);
wrapper.instance().methodName();
expect(spy).toHaveBeenCalled();

Comme on le trouve ici, par exemple : Test si la fonction est appelée react et enzyme

Veuillez noter il est également préférable d'effacer la fonction espionnée après chaque test.

let spy

afterEach(() => {
  spy.mockClear()
})

https://facebook.github.io/jest/docs/en/jest-object.html#jestclearallmocks

0 votes

Merci ! On dirait que c'est sorti en 19.0.0, il y a juste deux mois. Je n'arrive pas à croire que je ne l'ai pas vu dans la documentation.

0 votes

Est-ce qu'il appellera effectivement le methodName() dans le composant ou il fait juste semblant ?

0 votes

De la documentation : "Note : Par défaut, jest.spyOn appelle aussi la méthode spied." facebook.github.io/jest/docs/fr/

23voto

hloughrey Points 510

Je sais que c'est un peu tard, mais je suis tombé sur ce document et je vous suggère de le tester. componentDidMount initie l'appel à votre méthode imbriquée à laquelle votre test devrait ressembler :

Module

componentDidMount() {
  if (this.props.initOpen) {
    this.methodName();
  }
}

Test - Bon

it('should call methodName during componentDidMount', () => {
    const methodNameFake = jest.spyOn(MyComponent.prototype, 'methodName');
    const wrapper = mount(<MyComponent {...props} />);
    expect(methodNameFake).toHaveBeenCalledTimes(1);
});

Si vous appelez componentDidMount alors l'affirmation selon laquelle methodName a été appelé via componentDidMount est plus valable.

Test - Mauvais

it('should call methodName during componentDidMount', () => {
    const spy = jest.spyOn(Component.prototype, 'methodName');
    const wrapper = mount(<Component {...props} />);
    wrapper.instance().methodName();
    expect(spy).toHaveBeenCalled();
}

En écrivant le test comme ceci - vous appelez la méthode et ensuite vous affirmez qu'elle a été appelée. Ce qui sera le cas, bien sûr, puisque vous venez de l'appeler.

1 votes

Aucun de ces tests ne fonctionne pour moi, je n'arrive pas à le faire passer.

0 votes

Transmettez-vous tous les props nécessaires à votre composant ?

1 votes

J'ai finalement réussi à le faire fonctionner, j'ai dû créer une instance pour lui et forcer la mise à jour de mon espion.

0voto

Guentersniden Points 76

Si vous essayez de tester public les méthodes appelées sur componentDidMount (si vous utilisez TypeScript), vous devrez appeler explicitement la fonction instance 's componentDidMount puisque les méthodes publiques ne sont pas définies avant l'instanciation du composant.

Pour tester quelque chose comme ça :

Code

public componentDidMount() {
  if (this.props.initOpen) {
    this.methodName();
  }
}

public methodName = () => {
  // some code here
}

Test

it('should call methodName during componentDidMount', () => {
  const wrapper = mount(<MyComponent {...props} />);
  const instance = wrapper.instance();
  jest.spyOn(instance, 'methodName')
  expect(instance.methodName).toHaveBeenCalled();
});

0voto

Harish Gyanani Points 1160
const toastMethodSpy = jest.spyOn(sharedMockedOTPComponent, 'toast')
sharedMockedOTPComponent.handleResendOtpFailure(networkError)

//hide loader
expect(sharedMockedOTPComponent.state.showLoader).toBe(false)
//error message in toast should have been shown
expect(toastMethodSpy).toHaveBeenCalledTimes(1)

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