2009-08-28 10 views
30

本質的には、hTTPリダイレクトを送信してPHPを終了させるためのkillProgramというクラスのメソッドがあります。PHPUnitを使用して、その関数がPHPを終了させるはずの関数をテストするにはどうすればよいですか?

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

今私は、killProgram関数が例外をスローされたと考えられる例外をスローすることを考えています。

良い方法がありますか?

答えて

22

すべてのテストが同じPHPUnitのプロセスで実行されているとして、あなたは出口を使用すれば、/あなたのPHPコードで死ぬ、あなたはすべてを殺すだろう - あなたはそう^^

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

たぶんPHPUnitの3.4とそれが--process-isolationスイッチ(Optionally execute each test using a separate PHP processを参照)かもしれない(死んですべてのものを持っていないことによって)ヘルプだが、PHPUnitのがない場合、あなたはまだ、テストの結果を得ることができないだろうコントロールを戻す。

私はこの問題を2,3回経験しました。コールスタックで「十分に高い」状態に戻るために必要な場合には何度か戻ってくることもあります^^
最後に、私はもう「死ぬ」ことはないと思いますアプリケーション...それはおそらく、MVCについて考えるとき、btwより良いでしょう。

+0

今、私は例外をスローすることに決めました。問題は私のデフォルトの例外ハンドラがこの関数を呼び出すことを意図しているので、例外ハンドラが無視するkillProgramExceptionという新しい例外を作成する必要があります。ハッキーの種類 –

7

ので、ここに、私はあなたがすでにこのための答えを受け入れてきた実現し、それは古い質問ですが、私はこれが誰かのために役に立つかもしれません図:

代わりのdie()を使用して、あなたはthrow new RuntimeException()(またはを使用することができますあなた自身の例外クラスでもありますが、これはプログラムの実行を中断しますが(別の方法でも)、PHPUnitのsetExpectedException()を使用してキャッチします。その例外が発生したときにスクリプトをdie()にしたい場合は、ユーザのレベルに何も表示しないでください。set_exception_handler()を見てください。

具体的には、テストでは使用しないブートストラップファイルにset_exception_handler() -callを置くというシナリオを考えています。そのため、シナリオに関係なくハンドラはそこで起動しないため、何も干渉しませんPHPUnitのネイティブ例外処理を使用します。

+3

私の古い投稿が私の質問に答えると大好きです。 – stefgosselin

+0

この回答は、基本的には望ましくないフロー制御構造として例外を使用することを基本的に示唆しています。 –

13

コードをテストできるように変更する必要はありません。set_exit_overload()test_helpers、PHPUnitと同じ著者が提供しています)をそのまま使用することができます。

+1

lazyのリンク:https://github.com/php-test-helpers/php-test-helpers(これはphp.iniで有効にする必要があるPHP拡張です) –

+1

注:このプロジェクトはもはや維持されません(2014年以降)。 – amphetamachine

3

これは、テストに合格するためにいくつかのレガシーコードを取得している一連の問題に関連しています。だから私はテスト可能で)今、私は単純に(終了する呼び出しを置き換える

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

...このようなテスト可能クラスを作ってみた:: exitphp()。

テスト中の場合、私はUNIT_TESTINGを定義していますが、実際には生産していません。シンプルなモックみたいですね。

+0

IMO、これはとても優雅です。ありがとうございました。 –

+1

これは最初はうまく見えるかもしれませんが、これはテストのためだけにプログラムの動作を変えています。最後にはうまくいきませんIMHO –

16

これは明らかに古い質問ですが、私の提案は、die()のコードを別の方法に移動してから擬似的にすることです。一例として、代わりにこれを持っていることの

:あなたは簡単にterminate方法を模擬することができますし、心配する必要はありません

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); 
    } 
} 

その方法:

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

は、これを行いますあなたがそれを捕まえることができなくてもスクリプトは終了します。

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(); 
    } 
} 

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

あなたのテストでは、次のようになります。

関連する問題