2009-07-22 8 views
20

私はSimpleTestからPHPUnitに一連のテストを移行しようとしていますが、SimpleTestのpartial mocksに相当するものがあるかどうかは疑問でした。PHPUnitのSimpleTest "partial mocks"に相当しますか?

更新:この機能が利用可能であることを示唆しているドキュメントでは何も見つかりませんでしたが、私にはサブクラスを使用できるだけのものがありました。これは良いか悪い考えですか?リンク先のページを読んでから、

class StuffDoer { 
    protected function doesLongRunningThing() { 
     sleep(10); 
     return "stuff"; 
    } 
    public function doStuff() { 
     return $this->doesLongRunningThing(); 
    } 
} 
class StuffDoerTest { 
    protected function doesLongRunningThing() { 
     return "test stuff"; 
    } 
} 
class StuffDoerTestCase extends PHPUnit_Framework_TestCase { 
    public function testStuffDoer() { 
     $sd = new StuffDoerTest(); 
     $result = $sd->doStuff(); 
     $this->assertEquals($result, "test stuff"); 
    } 
} 
+0

サブクラスのアイデアをありがとう! – Kyslik

答えて

40

は、SimpleTestの部分モックは、メソッドの一部が上書きされている唯一のモックのようです。これが正しい場合、その機能は通常のPHPUnitモックで処理されます。 PHPUnit_Framework_TestCaseインサイド

、あなたはすべてのメソッドは何もしないし、nullを返しモックインスタンスを作成します

$mock = $this->getMock('Class_To_Mock'); 

とのモックを作成します。いくつかのメソッドをオーバーライドしたい場合は、getMockの2番目のパラメータは、オーバーライドするメソッドの配列です。

$mock = $this->getMock('Class_To_Mock', array('insert', 'update')); 

を指定するその戻り値のための準備ができて、取り出しinsertupdate機能をClass_To_Mockのモックインスタンスを作成します。

この情報はphpunit docsです。

、より多くの日付コードの例までthis answerショー、PHPUnitのバージョンは5.4

1

を開始するために私は、PHPUnitがテスト中のシステムのための部分的なモックをサポートしていないと思います。あなたがメソッドを分離しようとしているなら、私はあなたの実装がうまくいくと確信しています。

しかし、私はいくつかの理由から、これを避けようとしています。

まず、クラスの内部実装と非常に密接にテストを結合します。 doesLongRunningThingというメソッドが呼び出されたかどうか本当に気になりますか、「LongRunningThing」が完了したことがより重要になっていますか?

第2に、私はこれを実行すると、私は2つの仕事をする1つのクラスを持っているかどうか疑問に思う。 抽象クラスリファクタリングが順調である可能性があります。 doesLongRunningThing()が単一のメソッドであっても、独自のクラスになると、テストはずっと簡単になります。

あなたのSUTが依存しているサービスを注入するのが解決策だと思います(http://en.wikipedia.org/wiki/Dependency_injection)。これにより、DoesLongRunningThing実装のテストも容易になります。インタフェースに飛び込むなし

は、ここで私はどうなるのかです:

class DoesLongRunningThing { 
    public function execute() { 
     sleep(10); 
     return "stuff"; 
    } 
} 

class StuffDoer { 
    protected $doesLongRunningThing; 

    public function setLongRunningThinger(DoesLongRunningThing $obj) { 
     $this->doesLongRunningThing = $obj; 
    } 

    public function doStuff() { 
     return $this->doesLongRunningThing->execute(); 
    } 
} 

は、今ではモックに簡単です:

class StuffDoerTestCase extends PHPUnit_Framework_TestCase { 
    public function testStuffDoer() { 
     $dlrtMock = $this->getMock('DoesLongRunningThing'); 
     $dlrtMock->expects($this->any())->will($this->returnValue("test stuff")); 

     $sd = new StuffDoer(); 
     $sd->setLongRunningThinger($dlrtMock); 
     $result = $sd->doStuff(); 
     $this->assertEquals($result, "test stuff"); 
    } 
} 
+0

私はPHPUnitは単なるツールであり、テスト中のシステムは気にしません(これはツールユーザーのお取引です)。 Brentonの答えによると、PHPUnitは "部分的なモック"をサポートしています。最初の文の後に始まり、あなたの答えは完璧です(+1)。 –

8

PHPUnit_Framework_TestCase::getMock is deprecated since phpunit 5.4。代わりにsetMethodsを使用できます。

Mock BuilderオブジェクトでsetMethods(array $ methods)を呼び出して、設定可能なテストdoubleに置き換えられるメソッドを指定することができます。他のメソッドの動作は変更されません。 setMethods(null)を呼び出すと、メソッドは置き換えられません。

https://phpunit.de/manual/current/en/test-doubles.html

$observer = $this->getMockBuilder(Observer::class) 
       ->setMethods(['update']) 
       ->getMock(); 

上記getMockPHPUnit_Framework_MockObject_MockBuilder::getMockであることに留意されたいです。 (phpunit5.6)

関連する問題