私はこのチュートリアルに従っています: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.type
div であることが期待されているのに、私のケースではそうではないのはなぜですか。
浅いレンダリングを使用して高階コンポーネントで装飾された 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
。これは奇妙な副作用を引き起こす可能性があり、テスト側から行う必要があるため、デコレータが追加されるとテストとソースが同期しなくなる可能性があります。
ここではデコレータを使用しないのが安全な選択肢のようです。