web-dev-qa-db-ja.com

関数がPHPを強制終了することになっている場合、PHPUnitをどのように使用して関数をテストしますか?

基本的に、killProgramというクラスのメソッドがあります。これは、hTTPリダイレクトを送信してからPHPを強制終了することを目的としています。

これをどのようにテストする必要がありますか? phpunitを実行すると、そのテストでは何も返されず、完全に閉じます。

現在、killProgram関数に、処理されるべきではない例外をスローさせることを検討しています。これにより、例外がスローされたと断言できます。

もっと良い方法はありますか?

36
Zee Spencer

すべてのテストは同じPHPUnitプロセスによって実行されるため、PHPコードでexit/dieを使用すると、すべてを強制終了します-お気づきのとおり^^

だから、あなたは別の解決策を見つける必要があります、はい-死ぬ代わりに戻るような;または例外をスローします(テストされたコードが予期された例外をスローしたかどうかをテストできます)

たぶんPHPUnit3.4で、それは--process-isolation switch( オプションで個別のPHPプロセス を使用して各テストを実行する)mightを参照)ヘルプ(すべてが死ぬことはありません)、しかし、PHPUnitがコントロールを取り戻さない場合、テストの結果を取得することはできません。

私はこの問題を数回経験しました;死ぬ代わりに戻ることでそれを解決しました-必要に応じて数回戻って、コールスタックの「十分な高さ」に戻ることもできます^^
結局のところ、私のアプリケーションにはもう「ダイ」がないと思います... MVCについて考えるときは、おそらくもっと良いでしょう。

25
Pascal MARTIN

これは明らかに古い質問ですが、私の提案は、die()のコードを別のメソッドに移動してモックできるようにすることです。

例として、これを持つ代わりに:

class SomeClass
{
    public function do()
    {
        exit(1);
        // or
        die('Message');
    }
}

これを行う:

class SomeClass
{
    public function do()
    {
        $this->terminate(123);
        // or
        $this->terminate('Message');
    }

    protected function terminate($code = 0)
    {
        exit($code);
    }

    // or 
    protected function terminate($message = '')
    {
        die($message);
    }
}

そうすれば、terminateメソッドを簡単にモックでき、スクリプトをキャッチできずにスクリプトが終了することを心配する必要はありません。

テストは次のようになります。

class SomeClassTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @expectedExceptionCode 123
     */
    public function testDoFail()
    {
        $mock = $this->getMock('SomeClass');
        $mock->expects($this->any())
             ->method('terminate')
             ->will($this->returnCallback(function($code) {
                 throw new \Exception($code);
             }));

        // run to fail
        $mock->do();
    }
}

私はコードをテストしていませんが、動作状態にかなり近いはずです。

23
Andris

テストするためだけにコードを変更する必要はありません。set_exit_overload()(PHPUnitと同じ作成者からtest_helpersによって提供されます)を使用するだけです。

14
Craig Harris

あなたはすでにこれに対する答えを受け入れており、それは古い質問だと思いますが、これは誰かにとって役立つかもしれないと思うので、ここに行きます:

die()を使用する代わりに、throw new RuntimeException()(または独自の例外クラス)を使用できます。これにより、プログラムの実行が停止し(方法は異なりますが)、PHPUnitの setExpectedException() それをキャッチします。その例外が発生したときにスクリプトをdie()にし、ユーザーのレベルではまったく何も出力しないようにする場合は、 set_exception_handler() を確認してください。

具体的には、set_exception_handler()呼び出しをテストで使用されないbootstrapファイルに配置するため、ハンドラーが実行しないシナリオを考えています。シナリオに関係なくそこで起動するため、PHPUnitのネイティブ例外処理に干渉するものはありません。

7
pinkgothic

これは、テストに合格するためにいくつかのレガシーコードを取得してきた一連の問題に関連しています。だから私はこのようなテスト可能なクラスを思いついた...

class Testable {
   static function exitphp() {
      if (defined('UNIT_TESTING')) {
         throw new TestingPhpExitException();
      } else {
         exit();
      }
   }
}

ここで、exit()の呼び出しをTestable :: exitphp()に置き換えるだけです。

テスト中の場合は、UNIT_TESTINGを定義するだけですが、本番環境では定義しません。単純なモックのようです。

4
Peter Bagnall

環境変数の値に応じて、スクリプトを強制終了するか、例外をスローできます。

したがって、本番環境で強制終了するか、テスト環境で例外をスローします。

死ぬか終了するための呼び出しは、プロセス全体を強制終了します...

これはコメントのはずでしたが、評判ポイントのレベルでコメントすることはできません。

0
francis94c