使用Jest模拟React组件的依赖关系

时间:2017-03-30 14:01:25

标签: reactjs jestjs enzyme

我有一个反应组件(CreateForm)。 React组件依赖于模块(Store)。 CreateForm有一个Cancel按钮。单击取消按钮时,应调用Store模块的handleCancel函数。

我使用Jest写了一个测试失败:

test.only('should handle cancel button click', () => {
    jest.mock('../../src/store');
    const store = require('../../src/store');
    const wrapper = shallow(<CreateForm />);
    const cancelButton = wrapper.find('button').at(1);
    cancelButton.simulate('click');
    expect(store.default.handleCancel).toBeCalled();
});

测试失败。模拟函数没有被调用,测试失败。 react组件是否没有获得此版本的模拟?如果是这样,我该如何修复测试?感谢。

我的CreateForm组件如下所示:

import Store from './store';

render() {
   return (
     <Panel>
       <FormControls />
       <button onClick={Store.create}>Create</button>
       <button onClick={Store.handleCancel}>Cancel</button>
    </Panel>
  );
}

对我有用的第二个即兴测试如下所示。

test.only('should handle cancel button click', () => {
  const store = require('../../src/store').default;
  const cancel = store.handleCancel;
  store.handleCancel = jest.fn();

  const wrapper = shallow(<CreateForm />);
  const cancelButton = wrapper.find('button').at(1);
  cancelButton.simulate('click');
  expect(store.handleCancel).toBeCalled();

  store.handleCancel = cancel;
});

以上测试有效。我手动模拟函数,进行测试并在测试后将函数恢复到原来的状态。是否有更好的方式或Jest方式编写上述测试?感谢。

2 个答案:

答案 0 :(得分:1)

这就是我使用Jest设法监视导入函数的方法。

导入您正在测试的文件中导入的所有内容。

beforeEach中进行模拟,如果需要返回值或其他任何内容,可以使用更复杂的模拟。

afterEach调用jest.clearAllMocks()中将所有函数重置为正常,以阻止任何模拟进入其他测试。

把它们放在一起看起来像这样。

import shallow from 'enzyme'
import * as Store from './Store' // This should be the actual path from the test file to the import

describe('mocking', () => {
  beforeEach(() => {
    jest.spyOn(Store, 'handleCancel')
    jest.spyOn(Store, 'create')
  })

  afterEach(() => {
    jest.clearAllMocks();
  })

  test.only('should handle cancel button click', () => {
    const wrapper = shallow(<CreateForm />);
    const cancelButton = wrapper.find('button').at(1);
    cancelButton.simulate('click');
    expect(Store.handleCancel).toBeCalled();
  })
})

此外,如果您需要模拟默认导入,您可以这样做。 jest.spyOn(Store, 'default')

答案 1 :(得分:0)

你忘了告诉jest如何模拟商店模块,在你的情况下只是undefined

const store = require('../../src/store');
jest.mock('../../src/store', () =>({
 handleCancel: jest.fn()
}));

test.only('should handle cancel button click', () => {
    const wrapper = shallow(<CreateForm />);
    const cancelButton = wrapper.find('button').at(1);
    cancelButton.simulate('click');
    expect(store.default.handleCancel).toBeCalled();//I'm not sure about the default here
});

使用此解决方案,您可以告诉jest使用具有handleCancel功能的对象来模拟商店,这是一个开玩笑的间谍。在这个间谍你可以测试它被调用。