如何使用浅渲染测试装饰的React组件

egu*_*eys 17 javascript mocha.js reactjs react-jsx jestjs

我正在学习本教程:http://reactkungfu.com/2015/07/approaches-to-testing-react-components-an-overview/

试图了解"浅渲染"的工作原理.

我有一个更高阶的组件:

import React from 'react';

function withMUI(ComposedComponent) {
  return class withMUI {
    render() {
      return <ComposedComponent {...this.props}/>;
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

和一个组件:

@withMUI
class PlayerProfile extends React.Component {
  render() {
    const { name, avatar } = this.props;
    return (
      <div className="player-profile">
        <div className='profile-name'>{name}</div>
        <div>
          <Avatar src={avatar}/>
        </div>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

和测试:

describe('PlayerProfile component - testing with shallow rendering', () => {
  beforeEach(function() {
   let {TestUtils} = React.addons;

    this.TestUtils = TestUtils;

    this.renderer = TestUtils.createRenderer();
    this.renderer.render(<PlayerProfile name='user'
                                            avatar='avatar'/>);
  });

  it('renders an Avatar', function() {
    let result = this.renderer.getRenderOutput();
    console.log(result);
    expect(result.type).to.equal(PlayerProfile);
  });
});
Run Code Online (Sandbox Code Playgroud)

result变量保存this.renderer.getRenderOutput()

在教程中,result.type测试如下:

expect(result.type).toEqual('div');

在我的情况下,如果我记录result它是:

LOG: Object{type: function PlayerProfile() {..}, .. }

所以我改变了我的测试:

expect(result.type).toEqual(PlayerProfile)

现在它给了我这个错误:

Assertion Error: expected [Function: PlayerProfile] to equal [Function: withMUI]

所以PlayerProfile类型是高阶函数withMUI.

PlayerProfile装饰withMUI,使用浅渲染,只渲染PlayerProfile组件而不是它的孩子.如此浅的渲染不适用于我假设的装饰组件.

我的问题是:

为什么在教程result.type中应该是div,但在我的情况下不是.

如何使用浅层渲染测试使用高阶组件修饰的React组件?

Bri*_*and 20

你不能.首先让我们稍微去除装饰者:

let PlayerProfile = withMUI(
    class PlayerProfile extends React.Component {
      // ...
    }
);
Run Code Online (Sandbox Code Playgroud)

withMUI返回一个不同的类,因此PlayerProfile类仅存在于withMUI的闭包中.

这是一个简化版本:

var withMUI = function(arg){ return null };
var PlayerProfile = withMUI({functionIWantToTest: ...});
Run Code Online (Sandbox Code Playgroud)

您将值传递给函数,它不会返回,您没有值.

解决方案?保持对它的引用.

// no decorator here
class PlayerProfile extends React.Component {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以导出组件的包装和未包装版本:

// this must be after the class is declared, unfortunately
export default withMUI(PlayerProfile);
export let undecorated = PlayerProfile;
Run Code Online (Sandbox Code Playgroud)

使用此组件的普通代码不会更改,但您的测试将使用此代码:

import {undecorated as PlayerProfile} from '../src/PlayerProfile';
Run Code Online (Sandbox Code Playgroud)

另一种方法是将withMUI函数模拟为(x) => x(标识函数).这可能会导致奇怪的副作用,需要从测试端完成,因此在添加装饰器时,您的测试和源可能会失去同步.

不使用装饰器似乎是这里的安全选项.


Kam*_*aju 11

使用Enzyme通过一种名为dive()的方法测试更高阶/装饰器的浅层

点击此链接,了解潜水的工作原理

https://github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/dive.md

所以你可以用更高的顺序浅化组件,然后在里面潜水.

在上面的例子中:

const wrapper=shallow(<PlayerProfile name={name} avatar={}/>)
expect(wrapper.find("PlayerProfile").dive().find(".player-profile").length).toBe(1)
Run Code Online (Sandbox Code Playgroud)

同样,您可以访问属性并对其进行测试.