これは、AirBnBのReactテストライブラリEnzymeを使用して、私のReactコンポーネントのいくつかをリファクタリングしようとしているときに出会った興味深い問題です。Enzymeによるユニットユニットテストは、ヘルパー機能のコンテキストを再バインドしない
私の問題を説明する最善の方法は例であると思います。
test.js:
import React from 'react';
function renderInnerSpan() {
const {foo} = this.props;
if (foo) {
return <span>Foo is truthy!</span>;
}
return <span>Foo is falsy!</span>;
}
export default class extends React.Component {
render() {
return (
<div>
{renderInnerSpan.call(this)}
</div>
);
}
}
そして、ここでは、のためにテストスイートです。ここ
は、その親コンポーネントから受け取る小道具に応じたメッセージを表示する小さなリアクトコンポーネントです2つの通過試験とこの成分:
test.spec.js:
import Test from '../../src/test';
import React from 'react';
import {shallow} from 'enzyme';
import {expect} from 'chai';
describe('Test Suite',() => {
let renderedElement,
expectedProps;
function renderComponent() {
const componentElement = React.createElement(Test, expectedProps);
renderedElement = shallow(componentElement);
}
beforeEach(() => {
expectedProps = {
foo: true
};
renderComponent();
});
it('should display the correct message for truthy values',() => {
const span = renderedElement.props().children;
expect(span.props.children).to.equal('Foo is truthy!');
});
it('should display the correct message for falsy values',() => {
expectedProps.foo = false;
renderComponent();
const span = renderedElement.props().children;
expect(span.props.children).to.equal('Foo is falsy!');
});
});
これは問題なく動作しますが、テストコンポーネントの現在の実装は効率的ではありません。 .call(this)
を使用すると、render()
関数が呼び出されるたびに新しい関数が作成されます。私はそうのように、コンポーネントのコンストラクタでthis
の正しいコンテキストを結合することによってこれを避けることができます:この変更後
export default class extends React.Component {
constructor(props) {
super(props);
renderInnerSpan = renderInnerSpan.bind(this);
}
render() {
return (
<div>
{renderInnerSpan()}
</div>
);
}
}
、コンポーネントはまだ意図したとおりに動作しますが、テストが失敗開始:
AssertionError: expected 'Foo is truthy!' to equal 'Foo is falsy!'
Expected :Foo is falsy!
Actual :Foo is truthy!
私はコンストラクタにconsole.log(props.foo)
を追加しました。コンストラクタは、期待したときにコンストラクタが呼び出されていたことを確認し、受け取ったプロップは正しいと確認しました。しかし、console.log(foo)
をrenderInnerSpan
の内側に追加しました。foo
propを明示的にfalse
に設定してコンポーネントを再描画した後でも、値が常に真であるように見えます。
renderInnerSpan
は1度だけ結合し、Enzymeはすべての単一のテストでこれを再使用しているようです。だから、何を与える?私は期待した値でコンストラクタを呼び出すテストで自分のコンポーネントを再作成しています - なぜ私のバインドは古い値を使用し続ける関数ですか?
ご協力いただきありがとうございます。
ステートレス機能コンポーネントは、ここに行く方法のようです。私はやや異なるアプローチを取ってしまい、代わりに 'renderInnerSpan'をSFCに変えました。説明をありがとう、これは今より意味をなさないです。 –