如何模仿history.listen?

问题描述 投票:0回答:2

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,但是很想知道这个特定测试的最佳实践是什么

react-router enzyme browser-history history.js
2个回答
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!
})

0
投票

我最终做的就是这样。在第一个挂载它返回/,在第二个挂载它返回/second并从那里它回到默认状态0(/

jest.mock('./history', () => ({
  listen: jest
    .fn()
   .mockImplementationOnce(cb => {
      cb({ pathname: '/' });
    })
    .mockImplementationOnce(cb => {
      cb({ pathname: '/second' });
    }),
}));

和测试本身(在1个单一测试中测试/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);
  });

但是为了让我最初问过的测试工作就足够了:

jest.mock('./history', () => ({
  listen: cb => {
    cb({ pathname: '/second' });
  },
}));

我只是在嘲笑时不得不通过一个回调,所以接近我以前的,但有一些配对设法让它工作:)

希望它有意义,并将在未来帮助某人

© www.soinside.com 2019 - 2024. All rights reserved.