"无法读取属性_location of null"在Jest测试用例中使用React Apollo时

时间:2017-05-19 17:11:36

标签: javascript react-apollo

鉴于以下内容:

export function App() {
  return withApollo(<BrowserRouter>
    <MatchListRouteHandler />
  </BrowserRouter>);
}

// MatchListRouteHandler
export const Query = addTypenameToDocument(gql`
  query GetMatches {
    matches {
      id
    }
  }
`);

export default graphql(Query)(MatchListRouteHandler);

测试用例:

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
});

当Jest尝试运行测试用例时,我收到以下错误:

/home/dan/match-history-analyser/node_modules/jsdom/lib/jsdom/browser/Window.js:148
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location);
                                                                              ^

TypeError: Cannot read property '_location' of null
    at Window.get location [as location] (/home/dan/Projects/match-history-analyser/node_modules/jsdom/lib/jsdom/browser/Window.js:148:79)
    at Timeout.callback [as _onTimeout] (/home/dan/Projects/match-history-analyser/node_modules/jsdom/lib/jsdom/browser/Window.js:525:40)
    at ontimeout (timers.js:386:14)
    at tryOnTimeout (timers.js:250:5)
    at Timer.listOnTimeout (timers.js:214:5)

4 个答案:

答案 0 :(得分:2)

这似乎是因为Jest测试过程退出太快;在安装应用程序之后,Apollo会尝试继续请求您提供的数据,但是在测试结束后才会发生响应,导致这种神秘错误消息导致整个Jest跑步者退出。

这可以通过人为地增加有关测试结束前的延迟来解决,即:

it('renders without crashing', (done) => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);

  setTimeout(() => done());
});

请注意,这并不能完全修复错误(实际上,上面的测试将始终通过),但这确实意味着您的整个测试运行器不会完全炸毁。

正确答案可能涉及在测试中使用Server Side Rendering

答案 1 :(得分:1)

请注意这一点。我今天遇到了这个错误,也是Apollo + Jest,但是我修复了一个更优雅的方式,不确定,但我卸载了在afterEach中测试的组件。

beforeEach(() => {
    wrapper = mount(<Root location={ '/route/' } context={context} />);
})

afterEach(() => {
    wrapper.unmount();
});

答案 2 :(得分:0)

仅在渲染后卸载已创建的组件,

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);

  ReactDOM.unmountComponentAtNode(div); // unmounting the created component.
});

卸载组件应使错误消失。

答案 3 :(得分:0)

@ peter.mouland的回答对我有用。因为我正在测试组件可以由ReactDOM渲染,所以我实现了他的方法,如下所示:

describe('<MyComponent />', () => {
  const div = document.createElement('div');

  afterEach(() => {
    ReactDOM.unmountComponentAtNode(div);
  });

  it('deep renders without crashing', () => {
    ReactDOM.render(<MyComponen />,div);
  });
});