2011-04-23 20 views
2

私はユニットテストの初心者で、内部関数呼び出しを含む関数の単体テスト方法に固執しているようです。たとえば、次のようにテストします。内部関数呼び出しを持つ関数をテストする

public function getBlueFooCount($fooId) { 
    $foo = $fooDao->getFoosById($fooId); 

    // custom logic to pull out the blue foos from result set 
    // custom count business logic on blue foos ... 

    return $count; 
} 

内部機能の取得方法をどのように模擬することができますか?これは機能があまりにも強く結合しており、緩めなければならないためですか?

答えて

1

@ aibの答えをビルドするために、私たちのレガシーコードベース私たちのクラスの大半は緊密に結合されていて、多くのメソッドが新しいオブジェクトをインスタンス化していました。 Dependency InjectionInversion of Controlの実装を進めてきましたが、依然としてユニットテストが必要な何百ものクラスが残っていました。

レガシーメソッドの単体テストを書くときに、インスタンス化をリファクタリングして新しい小さなメソッドにしました。最高のパターンではありませんでしたが、それは安価であり、より大きなリファクタリングを行う必要なしに仕事を完了しました。

class FooCounter { 

    public function getFooDao(){ 
     return new FooDao(); 
    } 

    public function getBlueFooCount($fooId) { 
     /* was this 
     $fooDao = new FooDao(); 
     */ 
     $foo = $this->getFooDao()->getFoosById($fooId); 

     // custom logic to pull out the blue foos from result set 
     // custom count business logic on blue foos ... 

     return $count; 
    } 

} 

class FooCounterTest extends PHPUnit_Framework_TestCase { 

    public function test_getBlueFooCount(){ 
     $fooCounter = $this->getMock('FooCounter', array('getFooDao')); 
     $fooCounter->expects($this->any()) 
        ->method('getFooDao') 
        ->will($this->returnValue(new MockFooDao())); 

     $this->assertEquals(0, $fooCounter->getBlueFooCount(1)); 
    } 

} 

私たちが新しいクラスを実装していた場合、通常はコンストラクタベースのDIを使用しています。新しいものを作成する場合、私が与える答えです。私はそれが以前よりよく言われていると信じているので、他の人のリンクがあります(DRYの一種):Dependency Injection and Unit Testing。そして、あなたのケースのための各々のいくつかの例:

コンストラクタベースの注入

class FooCounter { 

    private $_fooDao 

    public function __construct($fooDao){ 
     $this->_fooDao = $fooDao 
    } 

    public function getBlueFooCount($fooId) { 
     $foo = $this->_fooDao->getFoosById($fooId); 

     // custom logic to pull out the blue foos from result set 
     // custom count business logic on blue foos ... 

     return $count; 
    } 

} 

class FooCounterTest extends PHPUnit_Framework_TestCase { 

    public function test_getBlueFooCount(){ 
     $fooCounter = new FooCounter(new MockFooDao()); 

     $this->assertEquals(0, $fooCounter->getBlueFooCount(1)); 
    } 

} 

セッターベース注入

class FooCounter { 

    private $_fooDao 

    public function setFooDao($fooDao){ 
     $this->_fooDao = $fooDao 
    } 

    public function getBlueFooCount($fooId) { 
     $foo = $this->_fooDao->getFoosById($fooId); 

     // custom logic to pull out the blue foos from result set 
     // custom count business logic on blue foos ... 

     return $count; 
    } 

} 

class FooCounterTest extends PHPUnit_Framework_TestCase { 

    public function test_getBlueFooCount(){ 
     $fooCounter = new FooCounter(); 
     $fooCounter->setFooDao(new MockFooDao()); 

     $this->assertEquals(0, $fooCounter->getBlueFooCount(1)); 
    } 

} 
+0

これは私が一緒に行った方向だったので、それが正しいことを確認するのを手伝ってくれてありがとう。 – jexx2345

+0

これはまさに私が念頭に置いていたものです。 – aib

2

$fooDaoをモックする必要があります。うまくいけばセッターやDIコンテナがあり、あなたはnewで作成していないでしょう。その場合、あまりにも強く結合されている可能性があります。

+0

は正しい方向に私を導いてくれてありがとう。 – jexx2345

関連する問題