6

私の質問はユニットテストについてです。以下のクラスがあると仮定します。

class X
{
    public function p1(){
       //logic
       $a = $this->p2();
       //more logic
    }

    public function p2(){
       //even more logic
    }
}

p1メソッドの単体テストを作成する場合、p2メソッドをモックする必要がありますか?

私が考えているのは、p1メソッド用に作成されたテストは、p2ではなくp1メソッドのみを実行してテストする必要があるということです。しかし、クラスXのモックを取得し、そのモックインスタンスで以下のようにp1メソッドを呼び出す必要があることを理解するために。

$xMock = $this->getMockBuilder('\X')
    ->setMethods(array('p2'))
    ->getMock();

$xMock->expects($this->any())
    ->method('p2')
    ->will($this->returnValue($value));

$resultTobeAsserted = $xMock->p1();

残念ながら、それを行うことは私には少し間違っていると感じます。このトピックについて同僚と話し合ったところ、SUT(テスト対象システム)をどのように定義するかということになりました。テスターがテストされている特定のメソッドをSUTと見なす場合、SUTから呼び出される他のメソッドは依存関係のように見え、当然テスターはそれらをモックしたいと思うでしょう。一方、テスターがクラス全体をSUTと見なす場合、それらのメソッド呼び出しはテストの一部になるため、それらをモックする理由はありません。

その結論は正しいですか?どのような考え方で、より堅牢な単体テストが得られますか?

4

3 に答える 3

3

p1メソッドの単体テストを作成する場合、p2メソッドをモックする必要がありますか?

いいえ。

クラスでメソッドを呼び出していて、何かが起こることを期待しています。

p2をモックすることで、クラスの実装の詳細に例外を設けることができます。

残念ながら、それを行うことは私には少し間違っていると感じます。

私はそれがその場で伐採すると言います。

どのような考え方で、より堅牢な単体テストが得られますか?

クラスの観察可能な動作をテストする場合は、クラスの実装を変更したときに、クラスが想定どおりに動作することを確認します。それは堅牢性です。

1つのメソッドをテストし、そのメソッドの実装の一部(内部メソッド呼び出し)をモックアウトする場合は、特定の実装をテストします。テストが失敗した場合は、外部の動作が変更されたかどうかはわかりません。


私はこれについてもう少し詳しく書いています:

The UNIT in unit testing.

これは、メソッドではなく動作をテストすることが重要であると私が考える理由について、さらにいくつかのポイントを詳しく説明しています。

要するに

PHPでの単体テストは、クラスの観察可能な動作をテストすることです。

行動:

  • 戻り値
  • 他のメソッドを呼び出す
  • グローバル状態の変更(ファイル、データベース、$ GLOBALSへの書き込み)

それらをテストします。実装の詳細は無視してください。

于 2013-02-01T14:55:40.017 に答える
2

テスターがテストされている特定のメソッドをSUTと見なす場合、SUTから呼び出される他のメソッドは依存関係のように見え、当然テスターはそれらをモックしたいと思うでしょう。

この分離をサポートする引数がある場合は、同じ引数を使用してクラスを2つのクラスにリファクタリングできます。これは、まさにその場合に行うべきことです。

于 2013-02-01T14:38:01.693 に答える
1

あなたの考えは正しいです。別のテストでテストされていると想定しているため、テスト方法p1が必要な場合は気にしません。p2だから、あなたはただモック/スタブすることができますp2。ただし、モック/スタブのみを使用する必要があることを覚えておく必要がありますp2。したがって、例は次のようになります。

$xMock = $this->getMockBuilder('\X')
    ->setMethods(array('p2'))
    ->getMock();

$xMock->expects($this->any())
    ->method('p2')
    ->will($this->returnValue($value));

$resultTobeAsserted = $xMock->p1();
于 2013-02-01T14:38:18.907 に答える