web-dev-qa-db-ja.com

サードパーティのコードをラップすることは、その消費者を単体テストする唯一の解決策ですか?

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

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

次に、Zend_Mailに依存する私のクラスLoggerを見てください。

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クラスは抽象ではなく構成に依存しているため、Dependency Inversionの原則に違反しています。

では、Zend_MailをラップせずにLoggerを個別にテストするにはどうすればよいですか。

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

13
Songo

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

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

サードパーティベンダーをすばやく変更できることは、大きな利点です。

21
Ben