浅いレンダリングで装飾されたReactコンポーネントをテストする方法 質問する

浅いレンダリングで装飾されたReactコンポーネントをテストする方法 質問する

私はこのチュートリアルに従っています: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}/>;
    }
  };
}

コンポーネント:

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

そしてテスト:

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

変数は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.typediv であることが期待されているのに、私のケースではそうではないのはなぜですか。

浅いレンダリングを使用して高階コンポーネントで装飾された React コンポーネントをテストするにはどうすればよいですか?

ベストアンサー1

できません。まず、デコレータを少しだけ脱糖しましょう。

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

withMUI は別のクラスを返すため、PlayerProfile クラスは withMUI のクロージャ内にのみ存在します。

簡略化したバージョンは次のとおりです。

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

関数に値を渡しても、関数は値を返さないので、値を取得できません。

解決策は?それへの参照を保持することです。

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

次に、コンポーネントのラップされたバージョンとラップされていないバージョンの両方をエクスポートできます。

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

このコンポーネントを使用する通常のコードは変更されませんが、テストではこれを使用します。

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

代替案としては、withMUI 関数を (アイデンティティ関数) としてモック化することです(x) => x。これは奇妙な副作用を引き起こす可能性があり、テスト側から行う必要があるため、デコレータが追加されるとテストとソースが同期しなくなる可能性があります。

ここではデコレータを使用しないのが安全な選択肢のようです。

おすすめ記事