Как шпионить за функциями вне компонента?

#jestjs #enzyme

#jestjs #фермент

Вопрос:

 // ./index.js
import { Component } from 'react';

export default class Test extends Component {
    method () {
        console.log('method()');
    }

    do () {
        this.method();
        func();
    }

    render () {
        return null;
    }
}

export function func () {
    console.log('func()');
}

// ./index.test.js
import { shallow } from 'enzyme';
import React from 'react';
import * as Test from './index';

describe('<Test>', () => {
    const component = shallow(<Test.default/>),
          method_spy = jest.spyOn(component.instance(), 'method'),
          func_spy = jest.spyOn(Test, 'func');

    test('func()', () => {
        component.instance().do();
        expect(method_spy).toHaveBeenCalledTimes(1); // passed
        expect(func_spy).toHaveBeenCalledTimes(1); // failed
    });
});
  

Я хочу шпионить за функцией вне компонента, но это плохо работает.

Я получил сообщение типа Expected mock function to have been called one time, but it was called zero times.

И я не хочу использовать метод mock() вместо spyOn() в данной ситуации.

Есть ли способ это исправить? Спасибо за чтение. 😀

Ответ №1:

Это не работает, потому что эта строка:

 const func_spy = jest.spyOn(Test, 'func');
  

…создает шпион для экспорта модуля для func

…но Test.do не вызывает модуль export для func , он вызывает func напрямую.


Есть два варианта исправить это.

Один из них заключается в перемещении func в его собственный модуль.

Затем модуль экспорта для него будет импортирован в index.js и вызван внутри Test.do

…и когда модуль экспорта для func обернут в шпиона, шпион будет вызван Test.do .


Другой вариант — отметить, что «модули ES6 автоматически поддерживают циклические зависимости», поэтому модуль может быть импортирован в себя.

Если модуль импортирован в себя, то Test.do можно вызвать модуль export для func :

 import { Component } from 'react';
import * as index from './index';  // <= import the module into itself

export default class Test extends Component {
  method() {
    console.log('method()');
  }

  do() {
    this.method();
    index.func();  // <= use the module
  }

  render() {
    return null;
  }
}

export function func() {
  console.log('func()');
}
  

…и шпион для экспорта модуля для func будет вызван, как и ожидалось:

 import { shallow } from 'enzyme';
import React from 'react';
import * as Test from './index';

describe('<Test>', () => {
  const component = shallow(<Test.default />),
    method_spy = jest.spyOn(component.instance(), 'method'),
    func_spy = jest.spyOn(Test, 'func');

  test('func()', () => {
    component.instance().do();
    expect(method_spy).toHaveBeenCalledTimes(1);  // Success!
    expect(func_spy).toHaveBeenCalledTimes(1);  // Success!
  });
});
  

Комментарии:

1. Вы правы! И я просмотрел эту часть Jest исходного кода. Я понял, что это произошло, потому что я не знал, как spyOn() работает. Спасибо.