【问题标题】:ShallowWrapper::setState() can only be called on class componentsShallowWrapper::setState() 只能在类组件上调用
【发布时间】:2019-08-11 11:51:17
【问题描述】:

此测试在我使用 withSnackbar 之前通过。但现在它失败了,我真的不知道如何解决这个问题。因此,任何帮助将不胜感激。谢谢。

这是我在组件中的导出:

export default withSnackbar(StoryApp)

这是我的测试:

let story = {
  Title: "title 1",
  body: "body 1",
  UserEntityKey: "userEntityKey",
  Key: "storyKey"
}

afterEach(() => {
  // cleaning up the mess left behind the previous test
  MockAxios.reset();
});

test('Story deletes based on mocked backend response', async () => {
  window.confirm = jest.fn()
  window.confirm.mockReturnValue(1);

  let idToken = "asdf"

  MockAxios.delete.mockImplementationOnce(() =>
    Promise.resolve(story.Key)
  )

  const storyApp = shallow(<StoryApp />);

  storyApp.setState((prev) => {
    prev.data.push(story)
    return prev
  })

  // Test without idToken
  await storyApp.instance().deleteStory(story)
  expect(MockAxios.delete).not.toHaveBeenCalled();
  expect(storyApp.state().data.length).toEqual(1)

  // Test with idToken
  storyApp.setState((prev) => {
    prev.user = { idToken: idToken }
    return prev
  })
  await storyApp.instance().deleteStory(story)
  expect(MockAxios.delete).toHaveBeenCalledWith(apiUrl + '?key=' + story.Key, { headers: { 'Authorization': idToken } });
  expect(storyApp.state().data.length).toEqual(0)
})

这是输出:

● 基于模拟后端响应的故事删除

ShallowWrapper::setState() can only be called on class components

  101 |   const storyApp = shallow(<StoryApp />);
  102 | 
> 103 |   storyApp.setState((prev) => {
      |            ^
  104 |     prev.data.push(story)
  105 |     return prev
  106 |   })

  at ShallowWrapper.setState (node_modules/enzyme/build/ShallowWrapper.js:639:17)
  at Object.setState (__tests__/App.test.js:103:12)
  at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
  at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:288:22)
  at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:114:21)
  at asyncGeneratorStep (__tests__/App.test.js:25:103)
  at _next (__tests__/App.test.js:27:194)
  at __tests__/App.test.js:27:364
  at Object.<anonymous> (__tests__/App.test.js:27:97)

【问题讨论】:

    标签: javascript reactjs react-redux jestjs


    【解决方案1】:

    制作像StoryApp local 这样的原始类会损害可测试性。导入的StoryAppwithSnackbar HOC 装饰,不是类组件。

    HOC 应该公开可用的原始组件,例如WrappedComponent 属性。

    或者一个模块应该同时导出装饰组件和原始组件:

    export class StoryApp ...
    
    export default withSnackbar(StoryApp)
    

    这样可以测试如下:

    import StoryApp, { StoryApp as OriginalStoryAppClass } from '...';
    ...
    const wrapper = shallow(<StoryApp />);
    const storyApp = wrapper.find(OriginalStoryAppClass).dive();
    

    【讨论】:

    • 谢谢@estus,但现在我得到了一些别的东西:方法“dive”意味着在 1 个节点上运行。找到了 0 个。你是什​​么意思 OriginalStoryAppClass? May 类名是 StoryApp,所以我用它来代替 OriginalStoryAppClass。
    • 类名无关紧要。 OriginalStoryAppClass 应该是原始类组件。如果您按照建议导出它,请像 import { StoryApp: OriginalStoryAppClass } 一样导入它。我不能说它不起作用的可能原因是什么,因为你没有提供你正在测试的代码。
    【解决方案2】:

    我的类定义如下所示:

    export class App extends React.PureComponent {}
    

    redux 存储定义如下:

    const AppStore = withDisclosureManager(connect(mapStateToProps, mapDispatchToProps)(injectIntl(AppStore)))
    
    export default EditModeQuestionnaireSectionDetailsStore
    

    当我开玩笑地导入应用程序时:

    // This doesn't work
    import { App } from './App' 
    
    // This works
    import App from './App'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-10
      • 2019-05-02
      • 2018-11-15
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      • 2021-09-30
      • 2017-12-30
      相关资源
      最近更新 更多