13

SimpleTestを使用していくつかのPHPコードを単体テストしていますが、問題が発生しました。データベースクラスのテストでは、PHP関数の期待値を設定できるようにしたいと思いmysqlます。関数のラッパークラスのテストでは、mailPHP関数をモックしたいと思いmailます。これらはほんの一例です。

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

私はRubyコードのテストの経験があり、Test :: UnitとRSpecを使用すると、コードを分離してテストするのが非常に簡単になります。私はPHPのテストに不慣れであり、テストに合格するために必要以上にテストしているように感じます。

SimpleTestやPhpUnit、またはこれを可能または簡単にする他のテストフレームワークに方法はありますか?

4

4 に答える 4

10

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

本当に主張する場合は、実行時にクラスと関数を再定義できるように、phpのプログラミングモデルを変更するrunkit拡張機能を使用できます。ただし、これは外部の非標準の拡張機能であるため、注意してください。デファクトスタンダードは、前述のように手動によるアプローチです。

于 2009-08-07T20:25:12.200 に答える
1

これは、グローバルphp関数のモックについて書いた興味深い記事です。著者は、SUT(テスト中のサービス)の名前空間内のメソッドを上書きすることにより、グローバルphp関数を「モック」(親切にする)するための非常に創造的なソリューションを提案します。

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

これが良い方法かどうかはわかりませんが、確かにうまく機能しているので、ここで言及する価値があると思います。議論のための食べ物かもしれません...

于 2016-04-13T10:25:44.943 に答える
0

runkitを内部で使用するPHPUnit拡張機能があり、呼び出しマッチャー、パラメーター制約、およびモックオブジェクトが実行できるすべてのことを使用できます。

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

于 2011-05-24T20:54:13.507 に答える
0

runkitPHP 5.3以降の環境では、名前空間をハッキングすることで拡張機能を使用する必要性を回避できます。関数呼び出しが-のような完全修飾名前空間を使用しないという唯一の要件は、\mysql_query()通常は使用しません。次に、名前空間でテストを定義することにより、テストで同じ関数を定義できます。PHPは、グローバル関数の代わりに関数を呼び出します。time()個人的には、このアプローチを使用して関数呼び出しをスタブ化します。これが嘲笑のフレームワークの良い例です

于 2015-08-31T06:04:17.950 に答える