1

いくつかのテスト ケースを書いていますが、モック オブジェクトを使用しているテスト ケースがあります。2 つのクラス メソッドが別のクラス メソッドから呼び出されているかどうかを確認する必要があります。これが私がやったことです:

まず、モックを生成しました。

Mock::generate('Parser');

次に、テスト内で次のように呼び出しました。

$P = new MockParser();

$P->expectOnce('loadUrl', array('http://url'));
$P->expectOnce('parse');

$P->fetchAndParse('http://url');

私の実装コードは次のようになります。

public function fetchAndParse($url) {
    $this->loadUrl($url);
    $this->parse();
}

そして、loadUrl および parse() メソッドは間違いなく存在します。テストで 2 つのエラーが発生しました。どちらも「[loadUrl] の予想される呼び出し回数は [1] で [0] になりました」というメッセージが表示されます。何が起こっているのかわかりません - メソッドはその関数から呼び出されています!

ありがとう、

ジェイミー

4

2 に答える 2

4

私の経験では .NET の世界でフレームワークをモックしてきましたが、あなたがやろうとしていることは間違っていると思います。

クラスのモックを作成するように求められると、モック フレームワークは、そのクラスのすべてのメソッドの「スタブ」を生成します。これには、メソッド fetchAndParse が含まれます。したがって、モック オブジェクト $P で fetchAndParse を呼び出している場合、メソッド loadUrl および parse は呼び出されません。あなたが実際に行っているのは、「スタブ化された」fetchAndParse メソッドを呼び出すことです。

私は PHP の経験があまりないので、テストを修正したくありません。うまくいけば、他の誰かがそれを行うことができます。

于 2009-05-24T13:33:37.730 に答える
1

モックの仕組みを誤解しています。依存性注入を使用してクラスにヘルパー オブジェクトを設定する場合、注入されたオブジェクトをモックできます。その後、元のオブジェクトの動作 (インターフェイス) をシミュレートできます。現在のインターフェイスを実装するクラスを作成せずに開発できるため、より良い方法はインターフェイスをモックすることです。

あなたの例では:

interface UrlLoaderInterface {

    public function load($url);
}

class YourParser {

    protected $urlLoader;
    protected $source;

    public function setUrlLoader(UrlLoaderInterface $urlLoader) {
        $this->urlLoader = $urlLoader;
    }

    public function fetchAndParse($url) {
        $this->loadUrl($url);
        $this->parse();
    }

    public function loadUrl($url) {
        $this->source = $this->urlLoader->load($url);
    }

    public function parse() {

    }

}

Mock::generate('UrlLoaderInterface', 'MockUrlLoader');

class TestYourParser extends UnitTestCase {

    public function testShouldCallUrlLoaderByFetchAndParse() {
        $testUrl = 'http://url';

        $urlLoader = new MockUrlLoader();
        $urlLoader->expectOnce('load', array($testUrl));
        $urlLoader->returns('load', 'source', array($testUrl));

        $parser = new YourParser();
        $parser->setUrlLoader($urlLoader);
        $parser->fetchAndParse($testUrl);
    }

}

ところで。メソッド名に「and」、「or」、「if」などの単語を含めることはできないため、あなたの例は失敗です...メソッドは1つのことしか実行できません。これらの単語を使用すると、コードの設計が悪いと確信できます。

于 2012-03-14T02:22:15.040 に答える