2009-08-07 14 views
10

私はSimpleTestでPHPコードをユニットテストしています。問題が発生しました。私のデータベースクラスのテストでは、PHPのmysql関数の期待値を設定したいと考えています。 関数のラッパークラスのテストで、私はPHPを模擬したいmail関数です。これらはほんの一部の例です。単体テストでのPHP関数の模擬

要点:私のメールクラスが電子メールを送信するかどうかを(常に)テストしたくないので、mail関数の呼び出し方法をテストしたいと思います。これらの関数が返すものを制御できるようにしたい。私は、データベース、フィクスチャ、その全体を必要とせずに、自分のデータベースクラスをテストできるようにしたい。

私はRubyコードのテストでいくつかの経験があり、Test :: UnitとRSpecはコードを単体でテストするのがとても簡単です。私はPHPを初めてテストするのですが、テストを成功させるためには、私が必要とする以上に多くのテストをしているように感じます。

SimpleTestやPhpUnitなどのテストフレームワークでこれを可能にする方法はありますか?

答えて

10

自動化された方法ではありません。あなたができることは、外部依存関係が外部から渡されるオブジェクトにラップされるような方法でコードを書くことです。実稼働環境では、実際のアダプタを接続するだけですが、テスト中にスタブやモックにワイヤリングできます。

あなたが本当に主張しているのであれば、実行時にクラスと関数を再定義できるように、PHPのプログラミングモデルを変更するrunkit extensionを使用することができます。しかしこれは外部の非標準の拡張であるため、そのことを念頭に置いてください。上記のように、デファクトスタンダードはマニュアルアプローチです。

+0

を参照してください。私はそのような答えを期待しています(しかし期待はしていません)。私はテストを単純化し、スピードアップしたいが、もっと複雑にしたくないので、本当に主張していない。お返事をありがとうございます! – avdgaag

+0

今すぐ[Mockery](http://docs.mockery.io/en/latest/cookbook/mocking_hard_dependencies.html)は[行く方法]ようです(http://stackoverflow.com/a/42158443/659788)。 – Franco

+1

@Franco組み込み用ではありません。 – troelskn

0

ランキットを内部的に使用するPHPUnit拡張モジュールがあり、呼び出しマッチャー、パラメータ制約、およびモックされたオブジェクトが実行できるすべてのものを使用することができます。

https://github.com/tcz/phpunit-mockfunction

0

はPHP 5.3+環境では、名前空間をハッキングによってrunkit拡張子を使用する必要性を回避することがあります。関数呼び出しが\mysql_query()のような完全修飾名前空間を使用しないという唯一の要件は、通常そうではありません。次に、名前空間でテストを定義することで、テストで同じ関数を定義することができます。そうすれば、PHPはグローバル関数の代わりに関数を呼び出します。個人的に私はこのアプローチを使用してtime()関数呼び出しをスタブします。ここにはnice example with the mockery framework

+0

[php-mock](https:// github。com/php-mock/php-mock)を使ってそのようなモックを作成します。 –

1

Here is an interesting articleがあります。グローバルなPHP関数を欺くことについて書いています。著者は、SUT(テスト対象のサービス)の名前空間の中のメソッドを上書きすることによって、グローバルphp関数を「模倣する(Mock)」ように非常に創造的な解決策を提案しています。 time機能が嘲笑されたブログ記事の例から、ここで

コード:これはそれを行うには良い方法があるが、それは確かにうまく機能し、私はそれが言及する価値があると思えば

<?php 

namespace My\Namespace; 

use PHPUnit_Framework_TestCase; 

/** 
* Override time() in current namespace for testing 
* 
* @return int 
*/ 
function time() 
{ 
    return SomeClassTest::$now ?: \time(); 
} 

class SomeClassTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @var int $now Timestamp that will be returned by time() 
    */ 
    public static $now; 

    /** 
    * @var SomeClass $someClass Test subject 
    */ 
    private $someClass; 

    /** 
    * Create test subject before test 
    */ 
    protected function setUp() 
    { 
     parent::setUp(); 
     $this->someClass = new SomeClass; 
    } 

    /** 
    * Reset custom time after test 
    */ 
    protected function tearDown() 
    { 
     self::$now = null; 
    } 

    /* 
    * Test cases 
    */ 
    public function testOneHourAgoFromNoon() 
    { 
     self::$now = strtotime('12:00'); 
     $this->assertEquals('11:00', $this->someClass->oneHourAgo()); 
    } 
    public function testOneHourAgoFromMidnight() 
    { 
     self::$now = strtotime('0:00'); 
     $this->assertEquals('23:00', $this->someClass->oneHourAgo()); 
    } 
} 

わかりませんここに。議論のためのいくつかの食べ物かもしれない...

関連する問題