web-dev-qa-db-ja.com

すべてのクラスのパブリックメソッドはインターフェイスから取得する必要がありますか?

私は現在TDD技術について学んでいます。提案の1つは、パブリックメソッドのみをテストし、プライベートメソッドをスキップすることです。モッキングについても読んでいます。特定のメソッドをモックしたい場合は、インターフェイスから取得するか、仮想としてマークする必要があります。アプリケーションの開発を開始したとき、単体テストの作成中にどのメソッドをモックするかわからないので、それらすべてをモックできるようにするのが最善だと思います。

すべてのメソッドを仮想化することが最善の解決策ではないと私は思います。その場合の代替策は、上記のインターフェースアプローチです。

それは正しい方向ですか、それとも明らかなものを見逃していますか?

4
ArturoO
  • ファビオは彼のコメントでそれに触れました-インターフェースや実装コードが存在する前にテストで依存関係を使い始めることは完全に合法です。

    テスト対象のオブジェクトに 間接入力 がどこかから必要であると感じた場合、またはオブジェクトの 間接出力 をテストする必要があると感じた場合は、スタブコードまたはモッキングコードの入力を開始します。これらの外部依存関係が存在していました。次に、IDE生産性機能を使用して、インターフェースとそのメソッドシグネチャを生成します。

    これは「 希望的思考によるプログラミング 」と呼ばれ、 outside-in TDD でよく使用されます。

    最初にそれらをモックしない限り、既存のインターフェース内に新しいインターフェースやメソッドを作成することはないので、あなたの質問はそのコンテキストではあまり意味がありません。

  • 別のコンテキストは、TDDサイクルのリファクタリングステップ中に新しいクラスを抽出して依存関係を作成し、より「クラシック」なスタイルで、モックでそれらをテストしないことを決定する場合です。

    ここで、あなたの質問に対する答えShould all class public methods come from an interface?は明確です:「いいえ」。オブジェクトAとBをテストするTDD記述のテストは、どちらもインターフェースを実装せずに完全に実行できます。

    ただし、このアプローチを使用するのは、抽出された依存関係が アプリケーション境界/シーム ではなく、テスト対象のオブジェクトと同じレイヤーにある場合のみです。アーキテクチャの境界にインターフェースを持つことは、通常、最も脆弱で、パフォーマンスが最も低く、構成が最も複雑で、同じ抽象化の複数の実装が必要になる可能性が最も高いため、多くの場合より価値があります。

7
guillaume31

すべてのクラスのパブリックメソッドはインターフェイスから取得する必要がありますか?

いいえ-実験するのは非常に興味深い制約ですが、必須ではありません。

特定のメソッドをモックしたい場合は、インターフェイスから取得するか、仮想としてマークする必要があります。

特定のメソッドをモックすることは私をぴくぴくさせます-オブジェクトではなくメソッドをモックしようとすると、オブジェクトに適切な粒度が実際にはないように聞こえ始めます。

その必要性に遭遇した場合、私は本当に2つのオブジェクトがあるかどうかを非常に注意深く調べます-1つはモックしたいビットに責任がある(そして他には何もない)と、前のオブジェクトをコラボレーターとして使用するもう1つです。

(- tdd のポイントの一部は、デザインがルールに違反している場合に敏感です。これは、デザインの弱点を示していることが多いためです。)

原則として、任意のパブリックメソッドをモックするneedすべきではないので、そのユースケースを時期尚早に最適化することはお勧めしません。

2
VoiceOfUnreason

私は現在TDD技術について学んでいます。提案の1つは、パブリックメソッドのみをテストし、プライベートメソッドをスキップすることです。

はい、TDDは最初に契約を通じてテストを定義し、後で実装を取得することに重点を置いています。まず、メソッド(主にパブリック)、それらの引数、戻り値の型、およびスローできる例外を定義します。

これらの契約は、interfacesまたはvirtual methodsからのものである場合とそうでない場合があります。それらは、新しいクラスの単なる空のメソッドである可能性があります。したがって、いいえ、それらはすべてインターフェイスからのものではありません。 TDDはそのように設計を強制しません。 1

モッキングについても読んでいます

ここであなたは迷子になっています。モック(IMO)は、テストのための高度な手法です。 TDDとは直接関係しません。モックなしでTDDをフォローできます。モックは、依存関係が大きいコンポーネントをテストするために対処されています(@ guillamue31が彼の回答でコメントしたとおり)。与えられたインターフェースの「偽の」インスタンスを提供します。テスト対象のユースケースに必要な条件を満たすためにプログラムできる動作。クラスかもしれません。はい、具象クラスもモックできます。

アプリケーションの開発を開始したとき、単体テストの作成中にどのメソッドをモックしたいかわからないので、それらすべてをモックできるようにするのが最善だと思います。

いいね。 TDDに、モックするのに適した候補となるコンポーネントを通知させます。 TDDを数回繰り返した後、テストが成功すると、デカップリングが必要なコンポーネントを簡単に確認できるため、候補をモック化できます。ただし、すべての依存関係がインターフェースを意味するわけではないことに注意してください。要件、ニーズ、好みに基づいて決定するのは、あなた次第です。


1:私は Sandro MancusoがRovers Mars kataを実装する のビデオを共有したいと思います。彼が契約をテストするためにインターフェースを使用しなかったことがわかります。 Mancusoはこの方法論を非常に支持しており、彼はすべての従業員にそれを奨励しています

2:SandroはTDDに従っており、Roverのメソッドは保護されていることに注意してください!!!彼はパッケージスコープで遊んでいます。テストと具象クラスは同じパッケージにあります。したがって、TDDはメソッドをパブリックとして定義することを強制することさえありません。

1
Laiv

いいえ。依存関係として使用されるクラスのインターフェースのみが必要です

例えば:

public class Application
{
     private IService service;
     public void Main() {...}
}

public class Service : IService
{
    public Customer GetCustomerForOrder(Order order)
}

public class Customer 
{
    public decimal GetBalance() {...}
}

public class Order 
{
    public decimal GetTotal() {...}
}

ここでは、サービスのみにインターフェースが必要です。アプリケーションをテストするとき、モック化されたサービスを注入したいと思います。インターフェースはそれを可能にし、さらに一般的な代替実装で置き換えます。

アプリケーションのモックはまったく役に立ちません。

依存関係がないため、顧客と注文を直接テストできます。

0
Ewan