Почему я не могу смоделировать функцию внутри jest.Mock (нужно использовать .mockImplementation для spyOn)? - PullRequest
0 голосов
/ 04 марта 2019

Я ожидал, что когда я смоделировал модуль с помощью jest.mock() и передал реализации функций каждому объекту, они перенесли бы в тесты.

import * as services from '_services';

// I thought this would be enough to mock 'load_basket'
jest.mock('_services', () => ({
  load_basket: jest.fn(() => Promise.resolve([]))
}));

describe('WB Component', () => {
  it('loads basket if basket prop is null', () => {

    // However, if I don't use .mockImplemenation here it gives
    // me an error that load_basket wasn't called
    const spy = spyOn(services, 'load_basket').mockImplementation(() => Promise.resolve([]));
    const wrapper = shallow(<WB basket={null} />);
    expect(spy).toHaveBeenCalled();
    wrapper.unmount();
    spy.mockRestore();
  });
});

Но я могу удалить реализацию функции в .mock и имею только load_basket: jest.fn(), но я не могу удалить .mockImplementation(() => Promise.resolve([])) внизу, или я получу expected spy to have been called, but it was not called.

Редактировать: Если у меня нет ни реализации функции в исходном .mock call или .mockImplementation, это даст мне TypeError: Cannot read property 'then' of undefined ... load_basket, являющийся 'неопределенным'.Это имеет смысл для меня, но я до сих пор не понимаю, почему насмешка над функцией в .mock делает ее отличной от той, что была показана в тесте?

Edit2: load_basket используется вследующим образом

class WB extends Component {
  constructor(props) {
    super(props);
    this.state = {
      basket: props.basket,
      loading_basket: !props.basket,
    };
  }

  componentDidMount(): void {
    if (!this.state.basket) {
      load_basket()
        .then(res => {
          this.setState({
            basket: res,
            loading_basket: false
          });
        })
        .catch( ... );
    }
  }

  render () { ... }
}

1 Ответ

0 голосов
/ 04 марта 2019

jest.mock принимает необязательный параметр factory, и если он указан, то module заменяется результатом вызова параметра factory.

Итак services.load_basket уже уже a фиктивная функция к моменту вызова вашей тестовой функции.


Сведения об ошибке

Вы звоните spyOn, что в итоге вызывает недокументированное наследие Jasmine spyOn функцию (Jest основано на Jasmine), я предполагаю, что вы хотели вызвать jest.spyOn.

Функция spyOn из Jasmine не работает корректно с фиктивной функцией Jest, которая в результате вызывает ошибку, которую вы видите, если вы несмоделируйте реализацию.

Обратите внимание, что если бы вы вызвали jest.spyOn, он просто вернул бы существующую фиктивную функцию , поскольку load_basket уже является фиктивной функцией, и она бы работала безфиктивная реализация.


С учетом всего вышесказанного вам не нужно шпионить за services.load_basket, поскольку этоуже фиктивная функция .

Ваш тест можно упростить до этого:

import * as services from '_services';

jest.mock('_services', () => ({
  load_basket: jest.fn(() => Promise.resolve([]))
}));

describe('WB Component', () => {
  it('loads basket if basket prop is null', () => {
    const wrapper = shallow(<WB basket={null} />);
    expect(services.load_basket).toHaveBeenCalled();  // Success!
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...