古くて(多くのparams)コンストラクターを持つ型がある場合、単体テストでスタブに使用する派生「偽」型を作成する目的で、保護されたパラメーターなしのコンストラクターを実装することは有効なアプローチですか?
別の方法はインターフェースを抽出することですが、これは、完全に制御できないコードベースでは必ずしも望ましいとは限りません...
古くて(多くのparams)コンストラクターを持つ型がある場合、単体テストでスタブに使用する派生「偽」型を作成する目的で、保護されたパラメーターなしのコンストラクターを実装することは有効なアプローチですか?
別の方法はインターフェースを抽出することですが、これは、完全に制御できないコードベースでは必ずしも望ましいとは限りません...
理想的ではありませんが、有効です。
私よりもこれについてよく知っている2人の人々を引用すると、The Art of Unit Testingで、Roy Osheroveは、ユニットテストがコードのユーザーのようであり、そのため、それらに特別にアクセスを提供することは必ずしも悪いことではないことについて話します。
そして、レガシーコードを効果的に使用する際に、Michael Feathersはそのようないくつかの手法について説明し、テスト用に保護することは、公開するよりも優れている可能性があることを指摘します。(実際、レガシーコードを使用している場合は、その本を読むことをお勧めします。
それがどのようなコードであるかによると思います-それがオーバーライドされるように設計されていることを意味するために人々が保護されたアクセスを取得する可能性が高いパブリックAPIである場合、それはおそらく悪い考えですが、それがかなり明らかに意味されていない典型的なビジネスアプリではオーバーライドされるので、問題はないと思います。私は確かにこの状況で時々それをします。
基本的に保護されたものをパブリックと同じように扱う必要があるため、厳密にオブジェクト指向の観点からは答えはノーになります。
ただし、それほど面倒ではない場合は、プライベートのパラメーターなしコンストラクターを追加し、リフレクションを介して呼び出すことができます。
テストしたいクラスを拡張するクラスを作成できませんか?これにより、インターフェースを作成せずに独自のコンストラクターを使用できます。
単体テストを容易にするためにコードまたはAPIを変更することは一般に望ましくないため(「プライベートメソッドを単体テストする必要があるか」の議論を参照)、既存のクラスを変更するのではなく、実際に新しいクラスを使用する方がよいでしょう。
非シール型は常に保護されたパラメーターなしのコンストラクターを宣言する必要があるという議論があります(他の型にはパラメーターがあります)。
これにより、サブクラスが独自の方法でクラスをインスタンス化できる柔軟性が得られ、基本コンストラクターにパラメーターを提供する必要がなくなります。
モックフレームワークは、独自の方法でクラスをインスタンス化できるようにする自由を望んでいるサブクラスのまさにそのような例です。モックオブジェクトは、とにかく戻り値をモックするため、プロパティのデフォルトや依存関係の設定を気にしません。
ある日、あなた自身のクラスや図書館の顧客は、クラスの設定について大きく異なる考えを持っているかもしれません。そして、不要になったものをベースctor。
どうしても初期化値を強制する必要がある場合はまれですが、まれです。構造体にパラメーターのないctorを含めるべきではないことに注意してください。