消費者を単体テストするための唯一のソリューションは、サードパーティのコードをラップすることですか?


13

私は単体テストを行っており、クラスの1つでメソッドの1つからメールを送信する必要があるため、コンストラクター注入を使用Zend_Mailして、Zendフレームワークにあるクラスのインスタンスを注入します。

現在、一部の人々は、ライブラリが十分に安定しており、頻繁に変更されない場合、それをラップする必要はないと主張します。したがって、それZend_Mailが安定しており、変更されず、私のニーズに完全に適合すると仮定すると、そのためのラッパーは必要ありません。

次にLogger依存する私のクラスを見てみましょうZend_Mail

class Logger{
    private $mailer;    
    function __construct(Zend_Mail $mail){
        $this->mail=$mail;
    }    
   function toBeTestedFunction(){
      //Some code
      $this->mail->setTo('some value');
      $this->mail->setSubject('some value');
      $this->mail->setBody('some value');
      $this->mail->send();
     //Some
   }        
}

ただし、ユニットテストでは、一度に1つのコンポーネントをテストする必要があるため、Zend_Mailクラスをモックする必要があります。さらに、クラスが抽象ではなく結石に依存するようになったため、依存関係反転の原則に違反してLoggerいます。

Loggerラップせずに単独でテストするにはどうすればよいZend_Mailですか?

コードはPHPにありますが、答えはそうである必要はありません。これは、言語固有の機能というよりも設計上の問題です


インターフェイスを使用する必要がありますか?PHPはダックタイピングをサポートしていませんか?
ケビンクライン

@kevinclineよく私はPHPを使用しました。これは、私が最も使用している言語だからです。しかし、実際にはPHPだけに限らず、問題の一般的な解決策を探しています。
松o

回答:


21

常に、インターフェイスの背後にサードパーティのタイプとメソッドをラップする必要があります。これは退屈で痛みを伴う場合があります。コードジェネレータを記述したり、ツールを使用してこれを行うことができます。

ただし、コード全体でライブラリのメソッドまたはタイプを使用するように誘惑されないでください。そもそも、ユニットテストの作成に問題があります。その後、ライセンスが変更されるか、サードパーティによってサポートされていないプラットフォームに移動すると、これらのタイプと依存関係が他のすべてのクラスに組み込まれていることがわかります。

サードパーティベンダーを迅速に変更できることは大きな利点です。


4
「あなたによって書かれていないもの」は少し多いです。標準またはプラットフォームの一部であるライブラリはラップするのが困難です。たとえば、すべての.NETコンポーネントをラップする必要はないでしょう。ラッパーがインターフェイスを通過するだけの場合、または生成されたコードである場合、テストを作成してもほとんどメリットがありません。そこにロジックがある場合(呼び出しの組み合わせなど)、テストが役立ちます。
ベン

3
最後の文に賛成。
Blrfl

1
適切にリファクタリングすると、ライブラリ機能の繰り返し使用はサービスクラスに含まれます。事前に定義する必要はありません。
ケビンクライン

3
-1:サードパーティのライブラリが標準化されたAPIを提供するサービスを提供する場合を除き、これは時間の浪費であり、コードを複製することで保守性を低下させるだけです。また、ヤグニ。
マイケルボルグワード

1
@MichaelBorgwardt:もちろんですが、その場合、標準APIがラッパーになり、ライブラリを簡単に交換できます。
Blrfl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.