web-dev-qa-db-ja.com

PHPUnitでsetUp()とtearDown()をどのように使用すべきかについての実際のWordの例はありますか?

メソッドsetUp()およびtearDown()は、各テストの前後に呼び出されます。しかし、本当に、なぜこれが必要なのかについて実際のWordの例はありますか?

他の人のテストを検査すると、常に次のようなものが表示されます。

public function setUp()
{
    $this->testsub = new TestSubject();
}

public function tearDown()
{
    unset($this->testsub);
}

public function testSomething()
{
    $this->assertSame('foo', $this->testsub->getFoo());
}

もちろん、この方法と「古い」ローカル変数の方法との間に実質的な違いはありません。

31
gremo

すべてのテストメソッドを個別に実行すると、テストコードは、テストするオブジェクトを作成するだけの多くの行を共有します。この共有コードは、setupメソッドに入ることができます(SHOULDではありません)。

次に、テストするオブジェクトを作成するために必要なことはすべて、setupメソッドに入ります。たとえば、テストするオブジェクトのコンストラクターに注入されるモックオブジェクトを作成します。

Setupへの次の呼び出しは、クラスのメンバー変数を新しいオブジェクトのセットで初期化するため、これを破棄する必要はありません。

ティアダウンが必要なのは、作成されたファイルやデータベースエントリなど、テストで永続的に何かが残っている場合だけです。そのようなことを行うテストを書くことは本当に良い考えではありませんが、ある時点で抽象化できなくなり、ハードドライブ、データベース、または実際のネットワークなどに触れる必要があります。

したがって、必要なティアダウンよりもはるかに多くの設定が必要です。このテストで実行する作業がない場合は、常にティアダウンメソッドを削除します。

モックに関しては、私はこのように働きます:

private $_mockedService;
private $_object;
protected function setUp()
{
    $this->_mockedService = $this->getMock('My_Service_Class');
    $this->_object = new Tested_Class($this->_mockService);
}

public function testStuff()
{
    $this->_mockedService->expects($this->any())->method('foo')->will($this->returnValue('bar'));
    $this->assertEquals('barbar', $this->_object->getStuffFromServiceAndDouble());
}
29
Sven

一連のフィクスチャオブジェクトをインスタンス化し、各テストで個別に作成する代わりに、各テストでインスタンス変数として使用できます。

SetUpでファイルハンドルのようなリソースを作成し、tearDownでそれらを閉じることを確認できます。一時ファイルを書き込んでいる場合は、それらを確実に削除できます。データベース接続を開く場合、それを閉じることができます(ただし、他の場所で行うこともできます-setupBeforeClass/tearDownAfterClassこれは、すべてのテストケースではなく、すべてのテストファイルに対して呼び出されます)。

それは一般的に持っているグルーヴィーなものであるちょうど前/後のフックです。あなたの人生を楽にするためにそれを使用するか、それを使用しないでください。

4
Koobz

受け入れられた回答の例にメモリリークがあります。 tearDownを追加する必要があります。

protected function tearDown()
{
    $this->_mockedService = null;
}

PHPUnitは、テストメソッド呼び出しごとに新しいテストケースオブジェクトを作成します。したがって、4つのテストメソッドがある場合、4つのオブジェクトがあり、4つのmockedServiceが作成されます。そして、スクリプト(テストスイート全体)が終了するまで削除されません。したがって、メモリリークを防ぐために、すべてのオブジェクトを削除し、tearDownのすべての変数を設定解除する必要があります。

2
Nick

テストするクラス内で依存関係がある場合は、ほとんどいつでもこれを使用できます。この典型的な例は、アプリケーションの状態を保存するある種のオブジェクト(セッションオブジェクト、ショッピングカートなど)です。

たとえば、カートオブジェクトで定義されたショッピングカートの内容の送料を計算するクラスがあるとします。そして、このショッピングカートが依存関係の注入を介して配送計算クラスに渡されたとしましょう。クラスのほとんどのメソッドをテストするには、カートオブジェクトを実際にインスタンス化してクラスに設定し、さまざまなメソッドを単体テストする必要があります。カートのアイテムも追加する必要があるかもしれません。したがって、次のような設定がある可能性があります。

public function setUp()
{
    $this->cart = new cart();
    $this->cart->add_item('abc');
    $this->cart->add_item('xyz');
}

また、テストメソッドが実際にカートのアイテムを変更し、送料情報でそれらを装飾するとします。あるテストから次のテストへの情報の流出を望まないため、最後にカートの設定を解除します。

public function tearDown()
    unset($this->cart);
}
1
Mike Brant