React js - How to mock Context when testing component

前端 未结 1 1692
庸人自扰
庸人自扰 2021-02-12 03:06

I\'m trying to test a component which inherits context from a root component, without loading/rendering everything from the root down. I\'ve tried and searched for examples on h

1条回答
  •  时光说笑
    2021-02-12 03:46

    I went into the same issue as you did and found out two ways of doing it.

    The first one is a basic copycat of your own way: Create a wrapper around my component and inject it with a dynamic context. I put the source code below for those interested, because it's ES6 unlike your example. But it's just to show how it would be done in ES6 and I do NOT recommend anyone using it (I haven't actually tested it myself).

    src/testUtils/mockWithContext.js

    import React, { Component } from 'react';
    import wrapDisplayName from 'recompose/wrapDisplayName';
    import hoistStatics from 'recompose/hoistStatics';
    
    export const defaultContext = {
      permissions: [
    
      ],
      user: {
        id: '1',
        display_name: 'Default user',
        email: '+default.user@gmail.com', // Trick with "+" for infinite aliases using gmail.
        username: 'default_user',
        created: '2016-08-01T15:50:13.246Z',
      },
    };
    
    export const defaultContextType = {
      permissions: React.PropTypes.array,
      user: React.PropTypes.shape({
        id: React.PropTypes.string.isRequired,
        display_name: React.PropTypes.string.isRequired,
        email: React.PropTypes.string.isRequired,
        username: React.PropTypes.string.isRequired,
        created: React.PropTypes.string.isRequired,
      }),
    };
    
    /**
     * HOC for context
     */
    const withContext = ({ context = defaultContext, contextType = defaultContextType }) => (WrappedComponent) => {
      class WithContext extends Component {
        getChildContext() {
          return context;
        }
    
        render() {
          return ;
        }
      }
    
      WithContext.displayName = wrapDisplayName(WrappedComponent, 'WithContext');
      WithContext.WrappedComponent = WrappedComponent;
      WithContext.childContextTypes = contextType;
    
      return WithContext;
    };
    
    export default hoistStatics(withContext);
    

    As I said, I wrote it, but didn't test it because I found a much better way of doing context-injecting when trying to write tests for this mock.

    Using Enzyme library, which is definitely built to support React components testing, there is the ability to shallow/mount/static render your component, for testing purpose. And each of these methods allow a second argument: the context.

    SimpleComponent.js

    const SimpleComponent = React.createClass({
      contextTypes: {
        name: React.PropTypes.string,
      },
      render() {
        return 
    {this.context.name}
    ; }, });

    SimpleComponent.test.js

    const context = { name: 'foo' };
    const wrapper = mount(, { context });
    expect(wrapper.text()).to.equal('foo');
    wrapper.setContext({ name: 'bar' });
    expect(wrapper.text()).to.equal('bar');
    wrapper.setContext({ name: 'baz' });
    expect(wrapper.text()).to.equal('baz');
    

    Pretty straight-forward. I didn't use it yet but it looks like what I (and you) wanted to do. I guess I'll just have to throw my own implementation to the garbage.

    http://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html

    0 讨论(0)
提交回复
热议问题