Redux: プロバイダーにラップされている、またはEnzymeに接続してコンテナーを参照することはできません

作成日 2016ĺš´03月20日  Âˇ  51コメント  Âˇ  ソース: reduxjs/redux

<Provider>とconnectで囲まれたものを参照できないようです

// test
let component = shallow(<Provider store={store}><ContainerComponent /></Provider>);
component.find('#abc'); // returns null

let component = shallow(<Provider store={store}><div id="abc"></div></Provider>);
component.find('#abc'); // returns the div node

// ContainerComponent
const Component = ({...}) => (<div id="abc"></div>);
export default connect(..., ...)(Component);

https://github.com/reactjs/redux/issues/1481でテストが酵素で記述された例をたどりましたが、コンテナーはそれらでテストされることはありません。 だから私はスマートコンテナをテストすべき/できるかどうかわかりませんか?

@fshowalter何かアイデアはありますか?

最も参考になるコメント

Reduxとは直接関係ありませんが。 コンテナでshallow()を再度呼び出すことで、これを解決しました。 ストア状態が渡された内部コンポーネントをレンダリングします。

例:

import React from 'react';
import {expect} from 'chai';
import {shallow} from 'enzyme';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import events from 'events';

const mockStore = configureMockStore([ thunk ]);
const storeStateMock = {
  myReducer:{
    someState: 'ABC'
  }
};

let store;
let component;
describe('tests for MyContainerComponent', () => {
  beforeEach(() => {
    store = mockStore(storeStateMock);
    component = shallow(<MyContainerComponent store={store} />).shallow();
  });

  it('renders container', () => {
    expect(component.find('div.somediv')).to.have.length.of(1);
  });
  ...
});

お役に立てれば

全てのコメント51件

connect()もProviderもこのライブラリの一部ではありません。 代わりに、適切なリポジトリ( https://github.com/reactjs/react-redux)にファイルされている場合は、そのような問題について話し合い、追跡する方が簡単です。

それは実際には理にかなっていると思います。 浅いレンダリングを行っているため、プロバイダーコンポーネントのみがレンダリングされます。つまり、ContainerComponentは、オブジェクト出力フォームまたは浅いレンダリングで生成されるものにそのまま残されます。

ここで2つの考え:

まず、 connect()によって生成されたラッパーコンポーネントは、実際にはcontext.storeを検索する前にprops.storeを検索するため、実際に接続されたコンポーネントをテストする必要があると感じた場合は、 、プロバイダーやコンテキストなどを気にすることなく、 <ConnectedComponent store={myTestStore} />をレンダリングできるはずです。

2番目の質問は、完全に接続されたコンポーネントを実際にテストすることについて本当に心配する必要があるかどうかです。 私が見た議論は、特定の小道具を使って「プレーン」コンポーネントをテストでき、 mapStateToProps実装をテストできれば、react-reduxがそれらを正しくまとめると安全に想定できるというものです。接続されたバージョン自体を実際にテストする必要はありません。

@gaearonそうですね、ごめんなさい。 これをreactで上げるか酵素レポで上げるかわからなかった。

@markeriksonスマートコンポーネントをテストする理由は、ラップされたコンポーネントによって適切なディスパッチャーが呼び出されたことを確認したかったmapToDispatchPropsのためです。 ストアをConnectedComponentに渡すだけで、状態マッピングやディスパッチコールバック関数をテストしません。

これについてもっと考え、必要に応じて関連するレポで問題を提起します。 助けてくれてありがとう。

@mordra :「正しいディスパッチャーが呼ばれた」と言うとき、実際には「正しいアクションクリエーター」を意味しますか?

あなたはこのようなことをすることができます(構文はおそらくオフですが、あなたはアイデアを得る必要があります):

let actionSpy = sinon.spy();

let wrapper = shallow(<PlainComponent someActionProp={actionSpy} />);
wrapper.find(".triggerActionButton").simulate("click");
expect(actionSpy.calledOnce).to.be.true;
expect(actionSpy.calledWith({type : ACTION_I_WAS_EXPECTING)).to.be.true;

つまり、プレーンコンポーネントをレンダリングし、 mapDispatchから返されたアクションである小道具のスパイを渡し、コンポーネントがそれらのアクションを呼び出すために必要な動作をトリガーします。

また、私の以前のコメントによると、 mapStateToPropsとmapDispatchToProps別々にテストでき、接続されたバージョンをテストすることなく、React-Reduxがそれらを適切に呼び出すことができるはずです。それが事実であることを確認するためにそれ自体。

@markerikson私のPlainComponentはアクションやアクションの作成者について知らないため、あなたが提案していることはできません。 これが正しい方法かどうかはわかりませんが、次のことを見てください。
https://github.com/mordra/cotwmtor/blob/master/client/charCreation/charCreation.jsx
私のmapDispatchToPropsにはすべてのロジックが含まれていることがわかります。

const mapDispatchToProps = (dispatch) => {
  return {
    onCompleted      : (player) => {
      Meteor.call('newGame', player, function (data) {
        console.log('new game return: ' + data);
      });
      dispatch(routeActions.push('/game'));
      dispatch({type: "INIT_GAME", map: generateAreas(), buildings: generateBuildings(dispatch)});
    },
    onCancelled      : () => dispatch(routeActions.push('/')),
    onChangeName     : input => dispatch(actions.changeName(input)),
    onChangeGender   : gender => dispatch(actions.setGender(gender)),
    onSetDifficulty  : lvl => dispatch(actions.setDifficulty(lvl)),
    onChangeAttribute: (attr, val) => dispatch(actions.setAttribute(attr, val))
  }
};

したがって、PlainComponentに渡された小道具をスパイした場合、正しいアクションが呼び出されているかどうかをテストすることはできません。むしろ、アクション作成者に渡されたパラメーターだけが正しいです。
次に、 connectコンポーネントを個別にテストする必要があります。

ああ。 それは私がもっと理解するのに役立ちます。

ですから、私が実際にテストを書く実際の経験はほとんどないという警告とともに、いくつかの考えがあります。

  • 実際に持っているのはアクションクリエーターです。 dispatchにアクセスしたいので、アクションクリエーターは個別に定義されていません。 それ自体は簡単にテストできません。 それらの動作もテストできるようにしたい場合があります。そのためには、 mapDispatchの外部でそれらを独自の関数として定義する必要があります。
  • これらはすべて、redux-thunkで使用するのに非常に適した候補のように見えます。これにより、これらの関数を独自に定義し、 dispatchにアクセスできるようになります。
  • あなたのPlainComponentは、「アクション」、または少なくともこの場合はコールバックについて知っています。つまり、それらを渡し、コンポーネントのどこかでthis.props.onSetDifficulty("HARD")などを実行しています。 私が行動のためにスパイを渡すことを提案したとき、これは私が置き換えることを提案したようなものです。 したがって、スパイをonSetDifficultyで渡した場合、コンポーネントがそれを呼び出したことを確認し、難易度の許容値を渡した可能性があります。

最終的には、 mapDispatchで定義されている関数を使用して、それらを個別に定義することで、物事をよりテストしやすくすることができるはずです。 そうすれば、コンポーネントを適切にテストするためにmapDispatchを接続する必要があることを心配する必要がなくなり、コンポーネントが適切な引数などを使用して特定のpropコールバックを呼び出したかどうかに焦点を当てることができます。

また、コンポーネントの観点からは、最終的には、 {action: CHANGE_NAME, name : "Fred"}がディスパッチされたかどうかについて実際に心配する必要はありません。 それが知っているのは、それがthis.props.onChangeName("Fred")と呼ばれていること、そして_that_があなたがテストしようとしているものであるということです-それは正しい方法でpropコールバックを呼び出しました。

@mordraの場合、 mapDispatchToPropsをエクスポートして、個別にテストします。 プロパティ名がすべて正しいことを確認し、スパイを渡してアクションクリエーターをテストすることができます。

とは言うものの、私はmapDispatchToPropsを避けて、単独で簡単にテストできるすでに形成されたアクションクリエーターをマップするmapActionCreatorsToPropsを優先する傾向があります。 その場合、インポートのタイプミスを防ぐためにすべての小道具が定義されていることをテストします。

最後に、通常の(浅くない)レンダリングを使用できることに注意してください。 そのためにはjsdomまたは実際のブラウザのいずれかが必要ですが、その後は任意のレベルを深くレンダリングできます。

これをreactまたは酵素レポで上げるかどうかわからなかった

申し訳ありませんが、ReactまたはEnzymeリポジトリを意味するものではありませんでした。 私はあなたが使用しているライブラリであるReactReduxを意味しました。

助けてくれてありがとう、それは私が行って消化するためのたくさんの情報です。 @markerikson @fshowalterもう少し調べて、mapState / Dispatchをエクスポートし、それらを個別にテストすることを提案します。期待されるアクションを呼び起こすコールバックをテストするのは理にかなっています。

@gaearonステートレスコンポーネントは、浅くて問題をすくい取るだけではレンダリングされません。ステートレスコンポーネントをネストしたステートフルコンポーネントのレンダリングに問題があるようです。そのため、今のところ、そのパスを回避するように心に留めておきます。

あなたが言及している問題がわかりません。 機能コンポーネントで浅いレンダリングをうまく使用できます。 ただし、浅いレンダリングは1レベルの深さでしか機能しません(コンポーネントがどのように定義されていても)。 これが主な機能です。再帰しないため、コンポーネントのテストは独立したままです。 再現できる浅いレンダリングに特定の問題がある場合は、Reactリポジトリに対してバグを報告してください。 ありがとう!

@gaearon :明確にするために、私がこれを行う場合:

let wrapper = shallow(<A><B /></A>);

Bはレンダリングされますか? それが元の質問だったと思うので、接続をテストするために、接続されたコンポーネントの周りに<Provider>をレンダリングしようとしました。

Reduxとは直接関係ありませんが。 コンテナでshallow()を再度呼び出すことで、これを解決しました。 ストア状態が渡された内部コンポーネントをレンダリングします。

例:

import React from 'react';
import {expect} from 'chai';
import {shallow} from 'enzyme';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import events from 'events';

const mockStore = configureMockStore([ thunk ]);
const storeStateMock = {
  myReducer:{
    someState: 'ABC'
  }
};

let store;
let component;
describe('tests for MyContainerComponent', () => {
  beforeEach(() => {
    store = mockStore(storeStateMock);
    component = shallow(<MyContainerComponent store={store} />).shallow();
  });

  it('renders container', () => {
    expect(component.find('div.somediv')).to.have.length.of(1);
  });
  ...
});

お役に立てれば

おそらくカスタムモジュールを介してこれを行うためのより親しみやすい方法を作成する必要がありますか?

編集:したがって、 component = shallowWithConnect()などのEnzymeの1つのメソッドとして接続を宣言できます

@ev1stensbergこれは素晴らしいアイデアです。 これがアプローチであるかどうか、および/またはこれに関する作業が開始されたかどうかを判断しましたか? そうでなければ、私は貢献したいと思います。

将来この問題に遭遇した人のために、これが私のために働くアプローチです:それ自体でプレーンコンポーネントをテストするだけです。 コンポーネント定義を名前付きエクスポートとしてエクスポートし、接続されたコンポーネント(アプリで使用するため)をデフォルトのエクスポートとしてエクスポートします。 元の質問のコードに戻ります。

// test
let component = shallow(<Provider store={store}><ContainerComponent /></Provider>);
component.find('#abc'); // returns null

let component = shallow(<Provider store={store}><div id="abc"></div></Provider>);
component.find('#abc'); // returns the div node

// ContainerComponent
export const Component = ({...}) => (<div id="abc"></div>); // I EXPORT THIS, TOO, JUST FOR TESTING
export default connect(..., ...)(Component);

次に、

const component = shallow(<Component {...props} />)
// test component

また、他の人が上で指摘したように、接続に渡す関数もカバーしている場合は、コンポーネント全体を完全にカバーしている必要があります。

さて、ここで最初に注意することは、 :

  1. ストアから
  2. に基づいてアクションをディスパッチして状態を変更しますイベント。

私が大丈夫なら、あなたは2つのことをテストする必要があるだけです:

  1. コンポーネントは、状態から生成された正しい小道具を受け取りますか(セレクターを介して行うことができます)?
  2. コンポーネントは正しいアクションをディスパッチしていますか?

これが私のアプローチです

import React from 'react';
import { shallow } from 'enzyme';
import { fromJS } from 'immutable';
import { createStore } from 'redux';
// this is the <Map /> container
import Map from '../index';
// this is an action handled by a reducer
import { mSetRegion } from '../reducer';
// this is an action handled by a saga
import { sNewChan } from '../sagas';
// this is the component wrapped by the <Map /> container
import MapComponent from '../../../components/Map';

const region = {
  latitude: 20.1449858,
  longitude: -16.8884463,
  latitudeDelta: 0.0222,
  longitudeDelta: 0.0321,
};
const otherRegion = {
  latitude: 21.1449858,
  longitude: -12.8884463,
  latitudeDelta: 1.0222,
  longitudeDelta: 2.0321,
};
const coordinate = {
  latitude: 31.788,
  longitude: -102.43,
};
const marker1 = {
  coordinate,
};
const markers = [marker1];
const mapState = fromJS({
  region,
  markers,
});
const initialState = {
  map: mapState,
};
// we are not testing the reducer, so it's ok to have a do-nothing reducer
const reducer = state => state;
// just a mock
const dispatch = jest.fn();
// this is how i mock the dispatch method
const store = {
  ...createStore(reducer, initialState),
  dispatch,
};
const wrapper = shallow(
  <Map store={store} />,
);
const component = wrapper.find(MapComponent);

describe('<Map />', () => {
  it('should render', () => {
    expect(wrapper).toBeTruthy();
  });

  it('should pass the region as prop', () => {
    expect(component.props().region).toEqual(region);
  });

  it('should pass the markers as prop', () => {
    expect(component.props().markers).toEqual(markers);
  });
  // a signal is an action wich will be handled by a saga
  it('should dispatch an newChan signal', () => {
    component.simulate('longPress', { nativeEvent: { coordinate } });
    expect(dispatch.mock.calls.length).toBe(1);
    expect(dispatch.mock.calls[0][0]).toEqual(sNewChan(coordinate));
  });
  // a message is an action wich will be handled by a reducer
  it('should dispatch a setRegion message', () => {
    component.simulate('regionChange', otherRegion);
    expect(dispatch.mock.calls.length).toBe(2);
    expect(dispatch.mock.calls[1][0]).toEqual(mSetRegion(otherRegion));
  });
});

@markeriksonどういう意味ですか:

mapStateToPropsの実装をテストできます

ES6エクスポートを介して接続されたコンテナをエクスポートするとします。 プライベートmapStateToPropsにアクセスすることはできません。 他の方法で話していましたか、それとも具体的にできますか?

@mordrax

プロパティ名がすべて正しいことを確認できます

したがって、mapStateToPropsを公開して公開し、テストからContainerComponentをレンダリングするとします。これには、偽のストアの送信や状態の小道具の送信も含まれます。次に、mapStateToPropsはその状態を受け取り、それを小道具にマップします。 しかし、その時点からどのようにテストできますか? ConnectはmapStateToPropsを呼び出して小道具をマージしますが、プレゼンテーションコンポーネントに設定されている小道具をインターセプトできるプロセス/フロー中のコードの継ぎ目はどこにあり、どのポイントが継ぎ目ですか? @ guatedude2のような二重の浅瀬は、継ぎ目なしでマップされた小道具をチェックする1つの方法かもしれないと思います...

あなたのshallow.shallowにも。 では、connect()コンポーネントは何を返しますか、ラッパーですよね? そして、そのラッパーは、プレゼンテーションコンポーネントをラップするものですか?

@granmoeは、あなたが正確に何を意味するかについて、これをより詳細に説明できますか?

connectに渡す関数もカバーしている場合は、コンポーネント全体を完全にカバーしている必要があります。

私はまた、テストしたい_what_とその理由に関して@tugorezと一緒にいます。

@markeriksonスパイとのとても良い例。 これはテストできることの1つですが、「動作の単位」をテストするには、さらに多くのアサーが必要になります。 スパイアクションがmapDispatchToPropsから呼び出されたことをテストするだけでは、コンテナコンポーネントの全体像はわかりません。 コンテナのハンドラロジックに基づいて期待される結果を表明することはありません。

小道具や状態に合格したことをテストするだけでは不十分です。コンテナコンポーネントの動作をテストする必要があります。 これは、2つのことをテストすることを意味します。

1)コンテナコンポーネントは小道具をプレゼンテーションコンポーネントに配線しましたか?もしそうなら、小道具からプレゼンテーションコンポーネントに渡された特定の状態に基づいてレンダリングされた後、プレゼンテーションコンポーネントが持つと予想される特定の状態がありますか? 誰が知っているか、おそらく何人かの愚かな開発者がやって来てmapStateToPropsにコードを追加しますが、それが適切にマップされると常に信頼できるとは限りません。それがコンテナロジックのテストのポイントです。 mapStateToPropsには実際にはロジックはありませんが、開発者がやって来て、そこにifステートメントをアドバタイズすることを知っている人は...まあ、それは物事を台無しにする可能性のある動作です。

2)ディスパッチハンドラロジック(動作)はコンテナ内で機能しますか。

@dschinkel :

Reduxに接続されたコンポーネントを定義するための一般的な方法は、 export default connect()(MyComponent)と、名前付きエクスポートとしてexport MyComponentを使用することです。 同様に、 mapStateは単なる関数であるため、 export const mapState = () => {}をインポートして、個別にテストすることもできます。

「コンテナコンポーネント」と「プレゼンテーションコンポーネント」のテストについて:ここでの一般的な考え方は、「コンテナ」===「の出力」のほとんどの部分でコンテナのテストについて心配する必要はないということです。 connect "。 React-Reduxには、それがどのように動作するかについての完全なテストスイートがすでにあり、その努力を複製する理由はありません。 ストアへのサブスクライブ、 mapStateおよびmapDispatchの呼び出し、およびラップされたコンポーネントへの小道具の受け渡しを正しく処理することを_知っています_。

ライブラリの利用者としてのあなたが興味を持っているのは、コンポーネントの動作です。 自分のコンポーネントがconnectラッパー、テスト、またはその他のものから小道具を取得しているかどうかは実際には問題ではありません。特定の小道具のセットが与えられた場合、そのコンポーネントがどのように動作するかが問題になります。

(また、FWIW、あなたは絶対にテストの専門家であり、私はそうではありませんが、あなたは物事について少しパラノイアになっているようです:) mapStateが心配なら誤って壊れた場合は、テストを作成して次に進みます。)

ここで、ラップされたコンポーネントがその内部で他の接続されたコンポーネントをレンダリングする場合、特に浅いレンダリングではなく完全なレンダリングを行う場合は、 const wrapper = mount(<Provider store={testStore}><MyConnectedComponent /></Provider>を実行することでテストする方がはるかに簡単です。 しかし、全体として、私の考えでは、ほとんどの場合、 mapState関数と「プレーン」コンポーネントを別々にテストできるはずであり、接続されたバージョンを確認するためだけにテストするべきではありません。 mapStateの出力がプレーンコンポーネントに渡されていること。

参考までに、Danが内部で何をするかを説明するためにしばらく前に書いたconnectのミニチュアバージョンを見るとよいでしょう: https ://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e。

つまり、mapStateToPropsとdispatchStateToPropsをエクスポートする場合は、それが良いでしょう。 connect()(私のテストの共同作業者)が機能することをテストしたくありません。間違いなくそうではありません。 これを行うための明確な方法の1つは、次の2つのメソッドをエクスポートすることです。

example-container-spec.js

describe('testing mapPropsToState directly', () => {
    it.only('returns expected state', () => {
        const state = {firstName: 'Dave'};
        const output = mapStateToProps(state);

        expect(output.firstName).to.equal('Dave');
    });
});

容器

import React from 'react';
import { connect } from 'react-redux'
import Example from './Example';

export const mapStateToProps = (state) => ({
    firstName: state.firstName
})

export default connect(mapStateToProps)(Example);

プレゼンテーション

import React, { Component } from 'react';

export default class Example extends Component {
    render(){
        return (
            <div className='example'>
                {this.props.firstName}
            </div>
        )
    }
}

次に、_shallow_レンダリングを使用して次のようなことを行い、子コンポーネントに飛び込むこともできます。

example-container-spec.js

it('persists firstName to presentation component', () => {
        var state = {firstName: "Dave"};
        const container = mount(<ExampleContainer store={fakeStore(state)}/>),
            example = container.find(Example);

        expect(example.length).to.equal(1);
        expect(example.text()).to.equal(state.firstName);
    });

容器

import React from 'react';
import { connect } from 'react-redux'
import Example from './Example';

const mapStateToProps = (state) => ({
    name: state.firstName
})

export default connect(mapStateToProps)(Example);

プレゼンテーション

import React, { Component } from 'react';

export default class Example extends Component {
    render(){
        return (
            <div className='example'>
                {this.props.firstName}
            </div>
        )
    }
}

これを浅くするさらに別の方法は、ダブルシャローを行うことです。 浅くなった親を浅くすると、子コンポーネントが浅くなり、そのラッピングは次のようになります。

it('get child component by double shallow()', () => {
        const container = shallow(<ExampleContainer store={fakeStore({})}/>),
            presentationalChildComponent = container.find(Example).shallow().find('.example');

        expect(presentationalChildComponent).to.have.length(1);
    });

つまり、これは別の方法です。プレゼンテーションコンポーネントの結果を確認しているのです。

どちらの方法でも機能します...ただし、あなたが言ったように、エクスポートされるmapStateToPropsはおそらく最良です。これは、プロップ状態の設定に関してテストすることだけを気にするからです。

私はあなたがテストの専門家であることを絶対に理解していますが、私はそうではありませんが、あなたは物事について少しパラノイアになっているようです:)

いいえ、そうではありません。正しくテストするということは、もろくなく、価値を提供する優れたテストを行うことが重要です。 まず第一に、誰も_専門家_ではありません。 誰もが継続的に学習しており、エゴのためにそれを認めたくない人もいます。 それはソフトウェア職人技(別名プロフェッショナリズム)と呼ばれています。

あなたが言ったように、振る舞いだけをテストし、共同作業者(connect()自体)をテストしないことが重要です。 それを初めて理解し、うまくテストすることが重要です。 共同作業者をテストしていないことを確認することは重要であり、それは時には仲間の開発者の間での議論を必要とします。

脆性テストを行うことができますが、脆性テストを行わないことが重要です。 テストは真剣に受け止められるべきであり、それはあなたがそれに正しく近づいているかどうかを継続的にチェックすることを意味します。 私は単に自分の流れを理解しようとしています。 私はTDDなので、どのように始めるかが重要であり、それには適切なテストが重要です。 したがって、Reactコンポーネントをテストするさまざまな方法を理解しようとするときに、誰も「妄想的」であると感じてはなりません。

新しいReactテストリポジトリが登場...
実際、react-reduxをテストするためのさまざまなスタイルと組み合わせ、およびアプローチを示すリポジトリをすぐに共有する予定です。 これを考えているのは私だけではないので、人々の助けになると思います。 reduxコンテナやその他のコンポーネントのテストに関して同じ質問をする人が何度もいます。 Reduxのドキュメントもreact-reduxのドキュメントもそれを正当化するものではなく、テスト領域IMOのドキュメントが不足しています。 それは表面を傷つけるだけであり、Reactテストへのアプローチに関するさまざまなスタイルを示す素敵なリポジトリが必要なので、すぐにそれを提示します。

If anyone would like to contribute to that repo, please get a hold of meなので、コラボレーターを追加できます。 例を追加してもらいたいです。 React Test Utils + mocha 、 Enzyme 、 Ava 、 Jest 、 tapeなどを使った例を見てみたいです。

結論:

私たちが議論した両方のアプローチは問題ないと思います。 メソッドを直接テストするか、上記のようにテストして、詳細に説明します。 壊れやすいテストを受ける可能性があるため、特定の方法に基づいてテストを行いたくない場合があります。そのため、過去にテストに悩まされたのはなぜですか。 したがって、1つの関数をテストするかどうか、それが「ユニット」をテストするかどうかは異なります。 メソッドを公開したくない場合もあります。その上でコントラクトをテストし、その一部を非公開にしておく方がよい場合があります。 したがって、テストを作成するときは、自分が頻繁に行っていることを考えることが常に重要です。 それは何も悪いことではありません。 良いテストを書くのは簡単ではありません。

それはまさにTDDが推進していることであり、それを頻繁に行っています。 そのため、よりスリムで脆弱性の低いコードになります。 TDDは、後でではなく、前もってテストすることを考えるように強制します。 それが違いであり、私のような人々がさまざまなフローやアプローチを理解したいと思う理由は、TDDを実行するときに、設計を小さなチャンクで頻繁に再評価する必要があるためです。つまり、テストアプローチについて頻繁に考える必要があります。

@markeriksonご入力いただきありがとうございます。テストについて話すのが大好きです。 いい人だ。 私はあなたの専門知識に疑問を投げかけていませんでした、ただ私が実際にmapStateToPropsを直接自分でテストしようとしたことがなかっただけです! テスターでないことで悪いことをしているわけではありません;)。 私は単にreduxを初めて使用するので、「表面に触れる」だけではない質問があります。 人々が自分のしていること、それをどのように行うことができるか、そして自分たちのアプローチから利益を得ているかどうかを人々が理解できるように、より低いレベルでテストについて話し合う必要があります。 そのためには、接続、react-redux、下位レベルのプロバイダーを理解する必要があります。これにより、「動作のみをテストする」方法を理解できます。 mapStateToPropsをエクスポートしている人はあまりいませんが、これは私にとっても興味深いことです...そして、なぜそうしないのか不思議に思います。

WeDoTDD.com
ところで、興味のある人のために、私は昨年WeDoTDD.comを始めました(Reactbtwで書かれています)。 特定のチーム(特定のチームのすべての開発者)のTDD、または会社全体(一部の企業にはすべてのTDD、特にコンサルティング会社の開発者がいます)の場合は、 slack.wedotdd.comで私に連絡してください。

アップデート。

接続されたコンポーネントをテストし、私にとって何がうまく機能しているかを振り返った後、私は@markeriksonのここでの声明に100%同意します。

接続されたコンポーネントをテストする必要があると実際に感じた場合は、レンダリングできるはずです。 プロバイダーやコンテキストなどについて心配する必要はありません。

テストに<Provider />を導入する必要はありません。それを行うと、 <Provider />が機能していることをテストするのではなく、共同作業者をテストしているように見えます。 コンポーネントの動作が機能することをテストする必要があります。コンテナがコンテキストを介してストアを取得しているかどうかは関係ありません。 ストアを小道具として渡すだけです。接続には、ストアにアクセスするための何らかの方法が必要です。テストでプロバイダーを完全に削除する方法(コンテキストまたは小道具)は関係ありません。

また、酵素のコンテキストオプションを使用する必要はないと思います。これは、Reactのコンテキストを介してストアを永続化できるもう1つの方法です。 テストでreactのコンテキストを完全に忘れてください。これはまったく不要な肥大化であり、テストがより複雑になり、保守と読み取りがはるかに困難になります。

mapStateToProps純粋関数をコンテナファイルにエクスポートして、直接テストします。 私はmapStateToPropsのテストと、コンテナを浅くテストするいくつかのテストの組み合わせを使用しており、プレゼンテーションコンポーネントが少なくとも期待する小道具を受け取っていることを確認してから、小道具のテストで停止します。 また、コンテナコンポーネントのテストでは二重浅化を行わないことにしました。 TDDは、そうしようとするとテストが複雑になりすぎて、おそらく何か間違ったことをしているというフィードバックを私に与えています。 その「間違った」とは、「コンテナコンポーネントのテストで浅いものを2倍にしない」ことです。 代わりに、プレゼンテーションコンポーネントの出力を個別にテストするプレゼンテーションコンポーネントテストの新しいスイートを作成します。

あなたが物事がうまくいったと聞いてうれしいです。 (FWIW、私のコメントは主に「継ぎ目」と「小道具を掘り下げる」についてのあなたの質問に答えたものでした。

<Provider> / context _is_を使用する必要があるのは、他の接続されたコンポーネントをレンダリングするコンポーネントの完全なレンダリングを行う場合です。これらの接続された子は、コンテキスト内のストアを探します。

テストに関するReduxの現在のドキュメントを改善するための提案がある場合は、必ずPRを提出してください。

マウントの@markerikson良い点。 ただし、テストしているコンポーネントのライフサイクルをテストする必要がある場合は、マウントのみを実行します。 子コンポーネントを深く掘り下げるためにそれを使用することはありません...それはもはや単体テストとして適格ではなく、基本的に統合テストであり、それらの子コンポーネントでそれらの子コンポーネントをテストする必要がある場合は、そのテストを実装の詳細に結合します親コンポーネントを介してではなく、単独で所有します。

とにかく良いもの、ありがとう!

つまり、 mountを使用して問題のコンポーネントのライフサイクルをチェックし、そのコンポーネントが他の接続されたコンポーネントをレンダリングする場合、エラーを回避するために、これらのネストされたコンポーネントのコンテキストでストアを使用できるようにする必要があります。テスト対象のコンポーネントがレンダリングされます。

(編集:私はどうやら自分自身を繰り返しているようです、申し訳ありません-常にスレッドを戻ったり、少し上にスクロールしたりせずに、複数の場所で質問に答える危険性があります。)

ああ、わかった! ええ、それについては考えていませんでした...

ここにすべてのコメントをありがとう、 @ markeriksonと@dschinkel! 彼らは非常に役に立ちます。 ここで、接続されていないコンポーネントをエクスポートして、他のコンポーネントと同じようにテストし、 mapStateToPropsとmapDispatchToProps別々にテストすることにしました。 ただし、これらのテストが検出されない場合が1つあります。それは、 map(State/Dispatch)ToPropsが実際にconnectの呼び出しに渡されない場合です。 例:

import React from 'react';
import { connect } from 'react-redux';

export const mapStateToProps = ({ name }) => ({ name });

export const Example = ({ name }) => <h1>{name}</h1>;

export default connect({ name } => ({ name: firstName }))(Example); // Whoops, didn't actually pass in `mapStateToProps`.

これは実際にはおそらく発生しないでしょうが、特にリンターがエクスポートされているため、未使用の変数としてmapStateToPropsを報告しないため、発生する可能性があります。

@danny-andrewsmapDispatchToProps関数をテストする方法について具体的に教えてください。

@leizard

mapDispatchToPropsまたはmapStateToPropsを直接テストしなくなりました。 このスレッド以来、私は考えを変えました。そうしないようにアドバイスします。

また、それらをテストすると、@ danny-andrewsの問題が発生しますが、問題は適切なテストに関するものであり、これら2つの関数を公開しようとすることはお勧めできません。 テストが終わった。 代わりに、動作をテストするか、浅いコンテナを介して小道具をテストすることにより、これら2つの方法を間接的にテストする必要があります。 これらのプライベートメソッドを公開しようとする理由はないことがわかり、公開しようとするのも悪いテスト方法であることに気づきました。

だから私は@markeriksonに同意しません、あなたの接続されたコンポーネントを通してテストしてください。

オーバーテストではなく、テストするのに適切なAPI/コントラクトを見つけることが重要です:)。

@dschinkel

動作をテストすることにより、これら2つの方法を間接的にテストする必要があります...
だから私は@markeriksonに同意しません、あなたの接続されたコンポーネントを通してテストしてください。

接続されていないコンポーネントを完全にエクスポートするのをやめ、接続されたコンポーネントのみをテストすることを提案していますか? それは「過剰なテスト」だと思います。 これにより、テストがテスト対象のコンポーネントの実装の詳細に不必要に結び付けられます。 接続されていないコンポーネントの機能(ある場合は、それはワームの他のすべての缶です)は、小道具を受け取る場所とは完全に無関係であるためです。 将来的には、そのコンポーネントを純粋なプレゼンテーションコンポーネントに変えたいと思うかもしれません。 接続されたコンポーネントをテストする場合は、すべてのテストを変更して、ストアを挿入せずに、小道具を直接渡す必要があります。 接続されていないコンポーネントをテストした場合は、接続されたコンポーネント固有のテストを吹き飛ばす以外に何もする必要はありません(詳細は以下を参照)。

ただし、 mapStateToProps / mapDispatchToPropsを直接テストするべきではないことに同意します。 これらのプライベートメソッドを単にテスト目的で公開することは、常にコードの臭いのように感じました。 実際、接続されたコンポーネントをテストする必要があるのはこれだけだと思います。 要約すると、次のようになります。

  1. 接続されていないコンポーネントと接続されているコンポーネントをエクスポートする
  2. mapStateToPropsまたはmapDispatchToPropsエクスポートしないでください
  3. 接続されていないコンポーネントを介してすべてのコンポーネントロジックをテストします
  4. reduxとの相互作用をテストする場合にのみ、接続されたコンポーネントをテストします(データプロップはストア内の適切な場所から渡されます/アクションプロップは適切なアクションクリエーターに割り当てられますなど)。

4番を実行する際の唯一の余分なオーバーヘッドは、接続されたコンポーネントに渡すためにreduxストアをスタブアウトする必要があることです。 ただし、APIは3つのメソッドにすぎないため、これは非常に簡単です。

MapStateToPropsメソッド

TestContainer.jsx:

import { connect } from 'react-redux';

export const TestContainer = ({ permissions }) => (permissions['view-message'] ? 'Hello!' : null);

export const mapStateToProps = ({ auth }) => ({ permissions: auth.userPermissions });

export default connect(mapStateToProps)(TestContainer); // Ewww, exposing private methods just for testing

TestContainer.spec.jsx:

import React from 'react';
import { shallow } from 'enzyme';

import TestContainer, { mapStateToProps } from './TestContainer';

it('maps auth.userPermissions to permissions', () => {
  const userPermissions = {};

  const { permissions: actual } = mapStateToProps({
    auth: { userPermissions },
  });

  expect(actual).toBe(userPermissions);
});

新しい方法

TestContainer.jsx:

import { connect } from 'react-redux';

export const TestContainer = ({ permissions }) => (permissions['view-message'] ? 'Hello!' : null);

const mapStateToProps = ({ auth }) => ({ permissions: auth.userPermissions });

export default connect(mapStateToProps)(TestContainer);

TestContainer.spec.jsx:

import React from 'react';
import { shallow } from 'enzyme';

import TestContainer, { TestComponent } from './TestContainer';

it('renders TestComponent with approriate props from store', () => {
  const userPermissions = {};
  // Stubbing out store. Would normally use a helper method. Did it inline for simplicity.
  const store = {
    getState: () => ({
      auth: { userPermissions },
    }),
    dispatch: () => {},
    subscribe: () => {},
  };
  const subject = shallow(<TestContainer store={store} />).find(TestComponent);

  const actual = subject.prop('permissions');
  expect(actual).toBe(userPermissions);
});

ええ、それは私がmapStateToPropsをエクスポートしてテストしないと言っていることです、それはテストを超えています。 APIを介してテストします。 ここでのAPIはコンテナです。

@ danny-andrews

接続されていないコンポーネントを介してすべてのコンポーネントロジックをテストします

いくつかの例を紹介できますか?

私はあなたが言ったときと同じことを意味します:「あなたは行動をテストすることによってこれらの2つの方法を間接的にテストするべきです」

用語を明確にするのに役立つかもしれません。「接続されていないコンポーネント」と言うときは、 connectの呼び出しにラップされている生のコンポーネントを意味し、「接続されているコンポーネント」と言うときは、から返される結果のコンポーネントを意味します。 connectへの呼び出し。 「連結成分」と「コンテナ」は同義語だと思います。 私の上から:

// Unconnected component. Test all component logic by importing this guy.
export const TestComponent = ({ permissions }) => (permissions['view-message'] ? 'Hello!' : null);

const mapStateToProps = ({ auth }) => ({ permissions: auth.userPermissions });

// Connected component (container). Only test interaction with redux by importing this guy.
export default connect(mapStateToProps)(TestComponent);

一部の人々は、これらを完全に分割し、「コンテナ」を純粋なプレゼンテーションコンポーネントをラップするconnectへの呼び出しにすることを好みます。 その場合、リストの1番と3番はなくなり、作成する必要のあるテストは、redux(4番)との相互作用を検証するテストのみになります。

私はこれについて巨大なブログ投稿を書くつもりです。 私は現在コードで忙しいですが、後で返信します

このスレッドを数回読んだ後、私は3つのアプローチが推奨されるという結論に達しました。

  1. mapDispatchToPropsとmapStateToPropsをエクスポートし、別々にテストします
  2. コンテナコンポーネントを浅くレンダリングし、配線が正しいことをテストします
  3. mapStateToPropsの代わりにセレクターを使用し、 mapDispatchToPropsの代わりにアクションクリエーターを使用して、それらを個別にテストします。 アクションクリエーター、レデューサー、セレクターを一緒に使用してテストを作成し、フロー全体が機能することを確認します。

結局、すべてのオプションは有効だと思いますが、それぞれ長所と短所があります。 「最も純粋な」はおそらく2番目のものですが、ほとんどの作業も含まれます。 私の個人的な好みは、実際にはオプション3に向かっています。
これについてはブログに詳しく書いていますが、コードサンプルもいくつかあります。

@ucorina
ES6モジュールの現在の世界では、各ファイルはそれ自体のスコープにラップされたモジュールと見なされます。 エクスポートは小さなモジュールのAPIであり、メソッドをエクスポートするのは非常に間違っていると感じます。そのため、メソッドをテストできます。 テストするためだけに、プライベートメソッドをパブリックにする方法も同様です。

そのため、私は@dschinkelアプローチに傾倒しており、mapDispatchとmapStateをエクスポートしていません。これは、これらが接続されたコンポーネントのプライベート実装であるためです。

ただし、接続の周りに別のコンポーネントをラップするだけのコンポーネントをどうするかはわかりません。

ブログ記事を書いたことはありますか? @dschinkelはそれを読みたいです

@AnaRobynn

ええ、 mapDispatchとmapStateをエクスポートするだけでは気分が悪く、おそらく自分では使用しないと思いますが、「純粋」ではないものの、有効なオプションです。 。 ダン・アブラモフがこの正確なテクニックをここで提案したので、私はそれを可能なオプションとしてそこに残しました: https ://github.com/reduxjs/react-redux/issues/325#issuecomment-199449298。

「接続の周りに別のコンポーネントをラップするだけのコンポーネントをどうするか」という質問に答えるために、私はそれをテストしないと言います。 アプリケーションに関連するビジネスロジックはなく、 connect実装をテストしたくありません。これはreact-reduxライブラリですでにテストされています。

それでもテストしたい場合は、コードを将来にわたって保証するために、 @dschinkelが説明しているものに近いここで説明する2番目のアプローチに従うことができます。

@ucorinaまさに、私もオプションだと思います! あなたの答えをより深く説明してくれてありがとう。 うまく書かれたブログ投稿です。 おめでとう!

@ucorinaもう一度ご迷惑をおかけして申し訳ありませんが、しばらく寝た後、オプション2にも完全に同意するかどうかはわかりません。 でもわかりません。 また、mapStateToPropsをテストすることの利点についてもまったくわかりません。

「オプション2」が間接的にアクションクリエーターもテストするのは良いと思いますか? また、セレクターを間接的にテストしますか? それは良いことですか?
私はそれで100%有罪判決を受けているわけではありませんが、そこにあるすべての(誤った)情報についても混乱しています。 テストには非常に多くの異なるアイデアがあります。

  1. mapStateToProps内のセレクターのみを使用してください

    • 必要に応じて、コンテナテスト中にそれらをモックします

    • セレクターを個別にテストします。

    • mapDispatchToProps内のアクションクリエーターのみを使用してください

    • 必要に応じて、コンテナテスト中にそれらをモックします。

    • アクションクリエーターを個別にテストします。

    • 接続されたコンポーネントを浅くする

    • レンダリングされていると主張する

    • mapStateToProps 、 mapDispatchToProps 、またはmergePropsに追加する必要があり、他の場所ではまだテストされていない追加のロジックをテストします。 (条件付きディスパッチ、 ownPropsから引数を取るセレクターなど)



      • この場合、モックが正しい回数、正しい引数で呼び出されたことをテストしているだけです。



別:

  • ストアの状態をモックして、コンテナーとセレクターを一緒にテストします
  • コンテナとアクションを一緒にテストするための外部API呼び出しをモックします

@AnaRobynn@ ucorinaの2番目のアプローチが正しいと思います。

私が聞いたことの多くは次のことを示唆しています。

  1. mapDispatchToPropsを公開し、直接テストする必要があります
  2. connect()はすでにテストされているため、connect()の呼び出しをテストする必要はありません。

1に関しては、テストのために内部を公開するのは良い習慣ではないと思います。 テストA:内部構造を想定し、B:実際にどのように使用されるかをテストする必要があります。

2に関しては、外部ライブラリを呼び出すものを_絶対に_テストする必要があります。 これは、あらゆるアプリケーションの破壊の弱点の1つです。 どのライブラリでも、マイナー/パッチバージョンのバンプで重大な変更が導入される可能性があり、テストをすばやく失敗させたいと考えています。

「オプション2」が間接的にアクションクリエーターもテストするのは良いと思いますか? また、セレクターを間接的にテストしますか? それは良いことですか?

はい、冗長なテストカバレッジは良いことです。

@philihp @dougbacelar
私はReactアプリケーションのテストに少し関連して成長したと思います。 私の現在の信念と主題についての考え:

  1. 複数のコンポーネントでこれらのマッピングが必要ない場合は、 mapStateToPropsとmapDispatchToPropsを公開しないでください。 テストのためだけにそれらをエクスポートすることは、アンチパターンです。
  2. 私は現在、コンテナーをコラボレーター(他の関数を委任する関数、およびそれらの他の関数が実際のロジックを実行する関数)と見なしています。
    どういう意味ですか?
  3. コンテナはロジックを実行しません
  4. 状態を選択するためのロジックは、セレクター関数用です(純粋に単体テストが可能です)。
  5. アクションのロジックは、アクションクリエーターに隠されています(これは、redux-thunkを使用しているかどうかによって異なります)。
  6. レンダリングされたビューは別の関数です(別のコラボレーター関数を持っているか、純粋にレンダリングする可能性があります

=>適切なテストライブラリを使用すると、実際のテスト設定は非常に簡単になります(testdouble.jsをお勧めします)。
=> testdouble.jsを介してセレクターとアクションをモックアウトします( td.when()を使用)
=>コンテナコンポーネントを浅くレンダリングします。ビューコンポーネントのメソッドにアクセスするには、 dive()を1回レンダリングします。
=> td.when()による一連のルールが与えられた場合、コンポーネントが正しく動作するかどうかをアサートします

fakeStoreライブラリを挿入する必要はありません。ストアをスタブアウトするのは問題ありません。

例:

/** <strong i="27">@format</strong> */

import React from 'react';
import { shallow } from 'enzyme';

function setup(props) {
  const HasOrganization = require('./HasOrganization').default;
  const defaultProps = {
    store: {
      subscribe: Function.prototype,
      getState: Function.prototype,
      dispatch: Function.prototype,
    },
  };
  const container = shallow(<HasOrganization {...defaultProps} {...props} />);
  return {
    container,
    wrapper: container.dive(),
  };
}

describe('<HasOrganization /> collaborations', () => {
  let getCurrentOrganizationId;
  beforeEach(() => {
    getCurrentOrganizationId = td.replace('../containers/App/userSelectors')
      .selectCurrentOrganizationId;
  });

  test('not render anything when the id is not valid', () => {
    const Dummy = <div />;
    td.when(getCurrentOrganizationId()).thenReturn(null);
    const { wrapper } = setup({ children: Dummy });

    expect(wrapper.find('div').length).toBe(0);
  });

  test('render something when the id is valid', () => {
    const Dummy = <div />;
    td.when(getCurrentOrganizationId()).thenReturn(1);
    const { wrapper } = setup({ children: Dummy });

    expect(wrapper.find('div').length).toBe(1);
  });
});

考え?

@AnaRobynnポイント1と2に強く同意します!

私のコンテナは通常非常に簡単です:

// imports hidden

const mapStateToProps = (state, { userId }) => ({
  isLoading: isLoading(state),
  hasError: hasError(state),
  placeholders: getPlaceholders(userId)(state), // a list of some sort
  shouldDoStuff: shouldDoStuff(state),
});

const mapDispatchToProps = {
  asyncActionPlaceholder,
};

export const mergeProps = (stateProps, dispatchProps, ownProps) => {
  return {
    ...stateProps,
    ...dispatchProps,
    ...ownProps,
    onMount: () => {
      if (stateProps.shouldDoStuff) {
        dispatchProps.asyncActionPlaceholder(ownProps.userId);
      }
    },
  };
};

export default compose(
  connect(
    mapStateToProps,
    mapDispatchToProps,
    mergeProps
  ),
  callOnMount(props => props.onMount())
)(SampleComponent);

だから私は

  1. すべてのセレクターとアクションクリエーターをスパイする
  2. テストgetPlaceholdersスパイが正しいuserIdで呼び出されました
  3. SampleComponentが正しい小道具でレンダリングされたことを表明する
  4. SampleComponent onMount shouldDoStuff===trueのときにモックアクションをディスパッチすることを確認します
  • 小道具に応じたものの条件付きレンダリングのようなもの私はSampleComponentの別のテストでテストします
  • また、 redux-mock-storeを使用して、 configureMockStore([thunk])()のようにストアをモックすることを好みますが、そうしないのは問題ないと思います...

TL; DR私は基本的に、テストセレクターのみが正しい引数で呼び出され、モックされたアクションが正常にディスパッチされ(ロジックに依存している場合)、子コンポーネントが正しいプロップでレンダリングされることを確認しました

@philihp

  • 私は外部ライブラリのテストに非常に反対です。すべてをモックして、物事を個別にテストすることを好みます。
  • エンドツーエンドのテストで、ライブラリのアップグレードによって引き起こされる大きな問題が検出されると確信しています。
  • コンテナー+セレクター+アクションクリエーターをすべて一緒にテストしたくない理由は、それらを再利用する他のすべてのコンテナーについて、同じセレクターとアクションクリエーターを再テストする必要があるためです。 その時点で、単体テスト自体にテストケースを追加する方がよいでしょう。

@dougbacelar表示したコンポーネントをテストするためのサンプルテストコードを教えてください。 酵素を使っていますか? 他に何かありますか? 浅い? マウント?

@dougbacelar

私は外部ライブラリのテストに非常に反対です。すべてをモックして、物事を個別にテストすることを好みます。

必要なときにモックアップしますが、本物を使用できるのであれば、どうでしょうか。 モックは、特定の通話が遅い場合や、ネットワーク要求などの副作用がある場合に役立ちます。

コンテナー+セレクター+アクションクリエーターをすべて一緒にテストしたくない理由は、それらを再利用する他のすべてのコンテナーについて、同じセレクターとアクションクリエーターを再テストする必要があるためです。 その時点で、単体テスト自体にテストケースを追加する方がよいでしょう。

はい、セレクター、アクションクリエーターを個別にテストします。 予想される多くの入力を使用して、それらを徹底的にテストします。

はい、コンテナもテストします。 それがセレクターとアクションクリエーターに重複するカバレッジを提供することを意味する場合、それは悪いことではありません。

これが私が意味することです...

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { saveColor } from '../actions/save';
import { selectColors } from '../reducers/colors.js';
import ColorButtons from '../components/ColorButtons';
const ColorButtons = ({ colors, onClick }) => (
  <div>
    {colors.map(color => {
      <button type="button" key={color} onClick={onClick(color)}>{color}</button>
    })}
  </div>
);
ColorButtons.propTypes = {
  colors: PropTypes.arrayOf(PropTypes.string),
  onClick: PropTypes.func.isRequired,
};
const mapStateToProps = state => ({
  colors: selectColors(state.colors),
});
const mapDispatchToProps = dispatch => ({
  onClickColor: color => () => {
    dispatch(saveColor({ color }));
  },
});
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ColorButtons);
import React from 'react';
import { shallow } from 'enzyme';
import configureStore from 'redux-mock-store';
import ColorButtons from '../ColorButtons';
import { saveColor } from '../../actions/save';
import { selectColors } from '../../reducers/colors.js';
const buildStore = configureStore();
describe('<ColorButtons />', () => {
  let store;
  let wrapper;
  const initialState = { colors: ['red', 'blue'] };
  beforeEach(() => {
    store = buildStore(initialState);
    wrapper = shallow();
  });
  it('passes colors from state', () => {
    expect(wrapper.props().colors).toEqual(selectColors(initialState.colors));
  });
  it('can click yellow', () => {
    const color = 'yellow';
    wrapper.props().onClick(color)();
    expect(store.getActions()).toContainEqual(saveColor({ color }));
  });
});

ここでは、これはselectColorsとsaveColorが取得できるすべての異なるパラメーターをテストしているわけではありません。 <ColorButtons />が作成されると、期待されるプロパティを取得することをテストしています。 絶対に別のテストでそれらをテストしてください。

import { selectColors } from '../colors.js';
describe('selectColors', () => {
  it('returns the colors', state => {
    expect(selectColors(['red'])).toEqual(['red'])
  })
  it('returns an empty array if null', state => {
    expect(selectColors(null)).toEqual([])
  })
  it('returns a flattened array', state => {
    expect(selectColors(['red', ['blue', 'cyan']])).toEqual(['red','blue','cyan'])
  })
})

私は外部ライブラリのテストに非常に反対です。すべてをモックして、物事を個別にテストすることを好みます。

必要なときにモックアップしますが、本物を使用できるのであれば、どうでしょうか。 モックは、特定の通話が遅い場合や、ネットワーク要求などの副作用がある場合に役立ちます。

部分的に同意しません。
私は外部ライブラリをモックすることはありません(所有していないものをモックしないでください)が、たとえばaxiosのラッパーを作成します。 コラボレーションテストでは、すべての機能をモックアウトして、すべてが正しく接続されていることを確認できます。

コラボレーションテストでは、モジュールや機能などを常にモックします。
共同作業者によって呼び出されるこれらの関数は、簡単に単体テストできます。

これが私が意味することです...

また、同意しません。
ここでは、レデューサーとセレクターを暗黙的にテストしています。 それがあなたがうまくやりたいことであるなら、私はこれらの関数をモックアウトして、それらが正しく呼び出されているかどうかをチェックすることを好みます。 残りはレデューサー/セレクターによって処理されます。

このスレッドは、 https: //martinfowler.com/articles/mocksArentStubs.html、Classical andMockistTestingで作成されたポイントを再ハッシュしています。

同意しました。 ロック。

このページは役に立ちましたか?
0 / 5 - 0 評価