如何嘲笑history.listen?

时间:2019-04-04 15:56:29

标签: react-router enzyme browser-history history.js

history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

在我的.js中,这就是我使用history.listen

的方式
import history from './history';

构造函数中的以下内容:

history.listen(location => {
  if (location.pathname === '/second') {
    this.setState({
      pathStep: 1,
    });
  } else if (location.pathname === '/') {
    this.setState({
      pathStep: 0,
    });
  }
});

现在,我正在为此进行有效的测试:

    I tried to do the following:
    jest.mock('./history', () => ({
      listen: () => () => {
        '/second';
      },
    }));

    it('changes activeStep when called', () => {
      expect(component.state().pathStep).toBe(1);
    });

但是即使在console.log之后添加history.listen(location => {,我也无法到达history.listen。所以我很好奇我在做什么错

我还尝试将spyOn添加到history.listen,但热衷于了解此特定测试的最佳做法是什么

2 个答案:

答案 0 :(得分:1)

如果模拟history.listen,则可以获取组件传递给它的回调

然后,您可以直接调用回调以验证您的组件是否正确响应。

这是一个完整的工作示例:

history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

code.js

import * as React from 'react';
import history from './history';

export class SimpleComponent extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = { pathStep: 0 };
  }
  componentDidMount() {
    this.unlisten = history.listen(location => {
      if (location.pathname === '/second') {
        this.setState({
          pathStep: 1,
        });
      } else if (location.pathname === '/') {
        this.setState({
          pathStep: 0,
        });
      }
    });
  }
  componentWillUnmount() {
    this.unlisten();
  }
  render() { return null; }
}

code.test.js

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

import { SimpleComponent } from './code';

test('SimpleComponent', () => {
  const listenMock = jest.spyOn(history, 'listen');
  const unlistenMock = jest.fn();
  listenMock.mockReturnValue(unlistenMock);

  const component = mount(<SimpleComponent />);
  expect(component.state().pathStep).toBe(0);  // Success!

  const callback = listenMock.mock.calls[0][0];  // <= get the callback passed to history.listen

  callback({ pathname: '/second' });
  expect(component.state().pathStep).toBe(1);  // Success!

  callback({ pathname: '/' });
  expect(component.state().pathStep).toBe(0);  // Success!

  component.unmount();
  expect(unlistenMock).toHaveBeenCalled();  // Success!
})

答案 1 :(得分:0)

我最终要做的就是这样。 在第一次安装时,它返回=IF(ISNA(B2)=FALSE,B2,IF(ISNA(C2)=FALSE,C2,IF(ISNA(D2)=FALSE,D2,IF(ISNA(E2)=FALSE,E2,"#N/A")))) ,在第二次安装时,它返回/,然后从那里返回默认状态0(/second

/

测试本身(在一个测试中同时测试jest.mock('./history', () => ({ listen: jest .fn() .mockImplementationOnce(cb => { cb({ pathname: '/' }); }) .mockImplementationOnce(cb => { cb({ pathname: '/second' }); }), })); /second

/

但是要使测试工作最初我要求这样的话就足够了:

it('changes pathStep when called', () => {
    expect(component.state().pathStep).toBe(0);

    component = mount(<MyComponent />);

    expect(component.state().pathStep).toBe(1);

    component = mount(<MyComponent />);

    expect(component.state().pathStep).toBe(0);
  });

模拟时,我只需要传递一个回调即可,与之前的回调非常接近,但是通过一些配对使它可以正常工作:)

希望这是有道理的,并将在将来对某人有所帮助