【问题标题】:Testing react component methods with HOC使用 HOC 测试反应组件方法
【发布时间】:2021-04-18 06:45:08
【问题描述】:

与主题一样,我想测试具有 HOC 的 React 组件方法。

通常我是这样做的:

describe('component method', () => {
  it('returns with null or undefined value', () => {
    const wrapper = shallow(<Component />);
    expect(wrapper.instance().methodName());
  });
});

但现在我有需要存储的组件,所以我正在尝试这样做:

describe('component method', () => {
  it('returns with null or undefined value', () => {
    const wrapper = shallow(<Component store={store} />);
    expect(wrapper.instance().methodName());
  });
});

当然 store 是定义的:

const mockStore = configureMockStore();
let store;

但我得到错误

TypeError: wrapper.instance().methodName is not a function

会不会是因为我的组件是这样包裹的?

export default withSocket(Component);

如果是,我该如何解决?

【问题讨论】:

  • 模拟 HOC 并仅测试组件就足够了吗?或者你想同时测试 HOC 和组件?
  • 我只是想测试组件,我不需要测试HOC,问题是组件具有加载状态并使用套接字从后端获取值,所以当它没有从后端获取值时它不会将加载状态更改为 false,因此不会渲染任何元素
  • 我认为您可以模拟 withSocket 或直接导出组件进行测试,因为 withSocket 应该在其他地方进行测试

标签: reactjs testing jestjs enzyme react-testing-library


【解决方案1】:

由于您只想测试组件,我建议您模拟 HOC。

为此,请使用jest.mock 并提供一个模拟实现

在你的测试文件中做:

import { forwardRef } from 'react';

jest.mock('./path-to-the-hoc', () => function withSocket(Component) {
  const MockWithSocket = forwardRef((props, ref) => {
    return (
      <Component
        {...props}
        // if you need to test instance methods, forward a ref here
        ref={ref}
        // additionally you can add props that the HOC would add here
        foo="bar"
       />
    );
  });

  return MockWithSocket;
});

describe('blah', () => {
  it('blah', () => {
    // render the component as you normally would,
    // the mock above works the module level and will swap
    // the real implementation for your mock above
  });
});

编辑:React 允许您通过 refs 访问实例方法。 HOC 添加了额外的抽象层,它会破坏 React 获取实例的方式,因此为了允许访问,您必须使用 forwardRef

【讨论】:

  • 嗯,我得到ReferenceError: Cannot access 'mockWithSocket' before initialization
  • 哦,我的错。我想那时我会内联它。我会更新我的答案
  • 我更改了它,但看起来我无法测试其中的功能...我尝试添加 const wrapper = shallow(&lt;Component /&gt;) 和 expect(wrapper.instance().methodName()) 但它不起作用,我得到 TypeError: Cannot read property 'methodName' of null
  • 啊要进入里面的方法,你可能需要转发参考。我会再次更新答案
  • 旁注:@Sowam 如果模拟 HOC 看起来很难,那是因为它是。 React 团队用 react hooks 替换了 HOC 模式,他们强烈推荐使用 hooks 覆盖类组件See here
【解决方案2】:

我想我找到了解决办法...

const mockStore = configureMockStore({});
const store = mockStore();

let wrapper;
beforeEach(() => {
    wrapper = shallow(<Component store={store} />)
        .dive()
        .dive();
});

describe("method", () => {
    it("returns correctly when prop is null or undefined", () => {
        expect(wrapper.instance().methodName(null)).toBe("Test");
        expect(wrapper.instance().methodName(undefined)).toBe("Test");
    });
});

我只是尝试使用dive(),但它没有用......它是在我添加第二个dive() 时开始的,但我仍然无法理解它有什么变化。是因为我在这个组件周围有 HOC,所以我必须“潜入”内部才能得到它还是什么?

【讨论】:

    猜你喜欢
    • 2018-08-20
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    • 1970-01-01
    • 2017-05-28
    • 2017-06-11
    相关资源
    最近更新 更多