Невозможно увидеть импортированную функцию в блоке compose в componentDidMount - PullRequest
0 голосов
/ 11 сентября 2018

Возникли некоторые проблемы с использованием spyOn для тестирования вызова метода внутри моего блока compose () для моего приложения Reactjs с использованием перекомпоновки, редукса и т. Д.

Базовая раскладка такова:

// index.jsx
import { foo, baz } from './lib';
const enhance = compose(
  foo(),
  lifecycle({
      componentDidMount() {
        baz();
      }
  });
);
export const MyComp = (...);
const mapStateToProps = state => (...);
export connect(mapStateToProps)(enhance(MyComp));

// lib.js
export const foo = () => {
  lifecycle({
      componentDidMount() {
        bar();
      }
  });
}
export const bar = () => {};
export const baz = () => {};

//index.test.jsx
import * as lib from '.libs';

describe('Test', () => {
  const didMountSpy = jest.spyOn(MyComp.prototype, 'componentDidMount');
  const fooSpy = jest.spyOn(lib, 'foo');
  const barSpy = jest.spyOn(lib, 'bar');
  const bazSpy = jest.spyOn(lib, 'baz');

  const wrapper = mount(<MyComp ... />);

  expect(didMountSpy).toHaveBeenCalledTimes(1); // PASS
  expect(bazSpy).toHaveBeenCalledTimes(1); // PASS
  expect(fooSpy).toHaveBeenCalledTimes(1); // FAIL
  expect(barSpy).toHaveBeenCalledTimes(1); // FAIL
});

Странная часть для меня, если вы посмотрите на baz () , я могу успешно ожидать вызова функции, когда она не заключена в другой метод в compse (). Но я не могу ожидать foo (), bar () . Я подозреваю, что есть некоторая странность в том, как фермент / шутка высмеивает методы жизненного цикла Reactjs.

Кто-нибудь сталкивался с чем-то подобным и имеет решения, позволяющие spyOn работать для вложенных методов в lifecycle.componentDidMount ()?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

fooSpy

fooSpy не вызывается, потому что foo вызывается при создании enhance, что происходит сразу после импорта index.jsx, поэтому foo ужебыл вызван к тому моменту, когда он был завернут в шпиона для создания fooSpy.

Если вы хотите отловить, что был вызван foo, вам нужно будет отложить создание enhance.

barSpy

bar() определяется локально в lib.js и вызывается непосредственно в определении foo.

jest.spyOn заменяет модуль экспорта из bar.Поскольку определение foo использует bar напрямую, а не экспорт модуля bar, замена экспорта модуля bar шпионом не влияет на вызов в foo и barSpy никогда не вызывается.

Если вы хотите отловить, что был вызван bar, вам нужно будет использовать модуль экспорта из bar в определении foo.


Вот рабочая версия теста:

lib.js

import { lifecycle } from 'recompose';
import * as self from './lib';  // import the module into itself

export const foo = () =>
  lifecycle({
      componentDidMount() {
        self.bar();  // call the module export for bar()
      }
  });
export const bar = () => {};
export const baz = () => {};

index.jsx

import * as React from 'react';
import { compose, lifecycle } from 'recompose';

import { foo, baz } from './lib';

export class MyComp extends React.Component {
  render() { return (<div>My Comp</div>); }
}

// use a function to delay the creation of enhance()
export const initialize = () => {
  const enhance = compose(
    foo(),
    lifecycle({
        componentDidMount() {
          baz();
        }
    })
  );
  return enhance(MyComp);
}

index.test.jsx

import * as React from 'react';
import { mount } from 'enzyme';

import * as lib from './lib';
import { initialize } from './index';

test('MyComp', () => {
  const fooSpy = jest.spyOn(lib, 'foo');
  const barSpy = jest.spyOn(lib, 'bar');
  const bazSpy = jest.spyOn(lib, 'baz');

  const MyComp = initialize();  // this will create enhance() which will call foo()
  const didMountSpy = jest.spyOn(MyComp.prototype, 'componentDidMount');

  const wrapper = mount(<MyComp />);

  expect(didMountSpy).toHaveBeenCalledTimes(1); // PASS
  expect(bazSpy).toHaveBeenCalledTimes(1); // PASS
  expect(fooSpy).toHaveBeenCalledTimes(1); // PASS
  expect(barSpy).toHaveBeenCalledTimes(1); // PASS
});
0 голосов
/ 12 сентября 2018

Вы должны использовать jest.mock метод для импровизированного импорта

Выполните следующие действия:

  • Создайте папку с именем __mocks__ в той же папке, где находится lib.js
  • Создайте файл с именем lib.js в папке __mocks__ и предоставьте фиктивную реализацию для foo, bar и baz методов / компонентов
  • В index.test.jsx не импортировать lib.js. Также перед импортом index.js в index.test добавьте следующую строку

jest.mock('path-to-lib/lib.js')

См .: https://jestjs.io/docs/en/manual-mocks

...