如何在构造函数内部使用上下文的情况下使用 jest 和酶来测试反应上下文?

Posted

技术标签:

【中文标题】如何在构造函数内部使用上下文的情况下使用 jest 和酶来测试反应上下文?【英文标题】:how to test react-context using jest and enzyme where context is used inside constructor? 【发布时间】:2020-03-02 14:50:58 【问题描述】:

我正在使用 react-context 来保存我的数据并访问构造函数中的数据,如下所示:

    class MyComponent extends Component 
      //constructor
      constructor(props, context) 
          super(props, context);

          const  testData  = this.context.storedData

          this.state=
          //maintained states
          
      
      //constructor ends
    

我正在尝试使用 jest 和酶框架测试反应上下文,但得到如下错误:

  TypeError: Cannot read property 'testData ' of undefined

  25 |   constructor(props, context) 
  26 |     super(props, context);
> 27 |     const  testData   = this.context.storedData
     |             ^

我已经尝试了大多数解决方案,但没有任何效果。我正在寻找适合我情况的完美解决方案。

【问题讨论】:

哇,旧版上下文 API。从未使用过它,您可以考虑转到现代Context API吗? 【参考方案1】:

从未使用过旧版上下文,its doc page 相当差。要测试依赖于上下文的组件,您必须传递该上下文,而且选项很少。

    Enzyme 的mount()/shallow() 提供second argument options,可用于传递上下文。但我不确定它是否适用于旧版上下文
const wrapper = mount(<MyComponent />,  context: storedData: testData: 1  );
    使用额外的包装器来提供上下文:
function createWrapperForContext (contextData) 
  return class Wrapper extends React.Component 
    getChildContext() 
      return contextData;
    

    render() 
      return this.props.children;
    
  ;

....
const ContextWrapper = createWrapperForContext(testData);
const elementWrapper = mount(<ContextWrapper><YourComponent /></ContextWrapper>) 

如果可能更喜欢迁移到现代的 Context API,那么它就更少了。

PS 为什么需要在构造函数中访问context?如果您在 render() 中使用它,您将永远不会担心“上下文已更新,但 render() 仍然引用旧值”。

【讨论】:

感谢@skyboyer 的解决方案我已经尝试过了,但对我没有用。解决我的问题的是:我在 test.js 文件中导入了所需的上下文并将测试写为:test("render", () =&gt; const props = //props we need to pass const contextData = //context data we need to pass const wrapper = mount(&lt;ContextName.Provider value=contextData&gt; &lt;ComponentName ...props /&gt;&lt;/ContextName.Provider&gt;) expect(wrapper.exists()).toBe(true); );【参考方案2】:

确实,传递带有上下文属性的选项甚至可以修复遗留上下文。

假设我们有color 上下文https://reactjs.org/docs/legacy-context.html

测试将是:

import  shallow, ShallowWrapper  from 'enzyme';
import React from 'react';

describe('MyComponent', () => 
  let component = ShallowWrapper<MyComponentProps>;

  // This will test the default color value
  it('should render with default context', () => 
    component = shallow(<MyComponent ...props/>);

    expect(component).toMatchSnapshot();
  );
  // testing with different context
  it('should render with context', () => 
    component = shallow(<MyComponent ...props />, 
      context: 
        color: 'red', // you still give it the default value.
      ,
    );

    component.setContext( color: 'purple' );
    component.instance().forceUpdate(); // you could call also render from instance
    expect(component).toMatchSnapshot();
  );
);

【讨论】:

以上是关于如何在构造函数内部使用上下文的情况下使用 jest 和酶来测试反应上下文?的主要内容,如果未能解决你的问题,请参考以下文章

使用Jest测试函数和内部if循环

在 Jest 测试框架中访问 Angular 服务构造函数

如何在没有冲突的情况下将 Mocha 和 Jest 与 TypeScript 一起使用?

使用 jest 模拟 AWS.DynamoDB.DocumentClient 的构造函数

从 ThreadLocal 到 AsyncLocal

扩展宿主函数自身的prototype属性