如何使用浅渲染测试装饰的 React 组件 [英] How to test decorated React component with shallow rendering

查看:18
本文介绍了如何使用浅渲染测试装饰的 React 组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我有一个高阶组件:

从'react'导入React;函数 withMUI(ComposedComponent) {用MUI返回类{使成为() {返回 <ComposedComponent {...this.props}/>;}};}

和一个组件:

@withMUI类 PlayerProfile 扩展了 React.Component {使成为() {const { name, avatar } = this.props;返回 (<div className="玩家配置文件"><div className='profile-name'>{name}</div><div><头像 src={头像}/>

);}}

和测试:

describe('PlayerProfile 组件 - 浅层渲染测试', () => {beforeEach(函数(){让 {TestUtils} = React.addons;this.TestUtils = TestUtils;this.renderer = TestUtils.createRenderer();this.renderer.render(<PlayerProfile name='user'头像='头像'/>);});it('渲染一个头像', function() {让结果 = this.renderer.getRenderOutput();控制台日志(结果);期望(result.type).to.equal(PlayerProfile);});});

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

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

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

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

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

所以我改变了我的测试:

expect(result.type).toEqual(PlayerProfile)

现在它给了我这个错误:

断言错误:预期 [Function: PlayerProfile] 等于 [Function: withMUI]

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

PlayerProfilewithMUI 装饰,使用浅层渲染,只渲染 PlayerProfile 组件,而不是它的子组件.所以浅渲染不适用于我假设的装饰组件.

我的问题是:

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

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

解决方案

你不能.首先让我们对装饰器稍微脱糖:

let PlayerProfile = withMUI(类 PlayerProfile 扩展了 React.Component {//...});

withMUI 返回一个不同的类,所以 PlayerProfile 类只存在于 withMUI 的闭包中.

这是一个简化版:

var withMUI = function(arg){ return null };var PlayerProfile = withMUI({functionIWantToTest: ...});

你将值传递给函数,它没有返回,你没有值.

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

//这里没有装饰器类 PlayerProfile 扩展了 React.Component {//...}

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

//这个必须在类声明之后,不幸的是用MUI(PlayerProfile)导出默认值;export let undecorated = PlayerProfile;

使用这个组件的普通代码不会改变,但是你的测试会使用这个:

import {undecorated as PlayerProfile} from '../src/PlayerProfile';

<小时>

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

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

I am following this tutorial: http://reactkungfu.com/2015/07/approaches-to-testing-react-components-an-overview/

Trying to learn how "shallow rendering" works.

I have a higher order component:

import React from 'react';

function withMUI(ComposedComponent) {
  return class withMUI {
    render() {
      return <ComposedComponent {...this.props}/>;
    }
  };
}

and a component:

@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>
    );
  }
}

and a test:

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);
  });
});

The result variable holds this.renderer.getRenderOutput()

In the tutorial the result.type is tested like:

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

in my case, if I log the result it is:

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

so I changed my test like:

expect(result.type).toEqual(PlayerProfile)

now it gives me this error:

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

So PlayerProfile's type is the higher order function withMUI.

PlayerProfile decorated with withMUI, using shallow rendering, only the PlayerProfile component is rendered and not it's children. So shallow rendering wouldn't work with decorated components I assume.

My question is:

Why in the tutorial result.type is expected to be a div, but in my case isn't.

How can I test a React component decorated with higher order component using shallow rendering?

解决方案

You can't. First let's slightly desugar the decorator:

let PlayerProfile = withMUI(
    class PlayerProfile extends React.Component {
      // ...
    }
);

withMUI returns a different class, so the PlayerProfile class only exists in withMUI's closure.

This is here's a simplified version:

var withMUI = function(arg){ return null };
var PlayerProfile = withMUI({functionIWantToTest: ...});

You pass the value to the function, it doesn't give it back, you don't have the value.

The solution? Hold a reference to it.

// no decorator here
class PlayerProfile extends React.Component {
  // ...
}

Then we can export both the wrapped and unwrapped versions of the component:

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

The normal code using this component doesn't change, but your tests will use this:

import {undecorated as PlayerProfile} from '../src/PlayerProfile';


The alternative is to mock the withMUI function to be (x) => x (the identity function). This may cause weird side effects and needs to be done from the testing side, so your tests and source could fall out of sync as decorators are added.

Not using decorators seems like the safe option here.

这篇关于如何使用浅渲染测试装饰的 React 组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆