2012-06-07 83 views
8

我正在編寫一個PHPUnit測試,我需要嘲笑一些依賴項,但是我仍然需要一些方法才能像以前一樣工作。也就是說,我有:PHPUnit:模擬除一些以外的所有方法

class Dependency { 
// some stuff not important for the test 
    public function thisOneINeed() { 
    /// complex code 
    } 
// some more stuff 
} 

所以我在做這樣的事情:

// prepare mock object 
$dep = $this->getMockBuilder('Dependency')->disableOriginalConstructor()->getMock(); 
// mock out some other method that should return fixed value 
$dep->expects($this->any())->method("shouldGetTrue")->will($this->returnValue(true)); 
// run test code, it will use thisOneINeed() and shouldGetTrue() 
$result = $testSubject->runSomeCode($dep); 
$this->assertEquals($expected, $result); 

,一切都很好,除了方法thisOneINeed()被戲弄了,所以我不明白複雜的代碼運行和我需要它運行runSomeCode()才能正常工作。 thisOneINeed()中的代碼不會調用任何其他方法,但它需要進行適當的測試,並且它不返回固定值,所以我不能只將靜態returnValue()放在那裏。而AFAIK PHPunit沒有類似returnValue()的方法,稱爲「call parent」。它有returnCallback(),但我無法告訴它「爲父類調用此方法」,據我所知。

我可以做的所有方法的列表中Dependency,從中取出thisOneINeed,構建模擬時,它傳遞給setMethods(),但我不喜歡這種做法,看起來缺憾。

我也可以這樣做:

class MockDependency extends Dependency 
{ 
    // do not let the mock kill thisOneINeed function 
    final public function thisOneINeed() 
    { 
     return parent::thisOneINeed(); 
    } 
} 

,然後用MockDependency打造的模擬對象,而這個工作過,但我不喜歡做手工模擬。

那麼有沒有更好的方法來做到這一點?

回答

9

我認爲,如果你想使用PHPUnit的模擬生成器,然後創建的所有方法的數組,除去一個你需要的,並將它傳遞給setMethods正是你需要做的事。

我個人認爲應該在很多情況下,有ReflectionClass的子類,我可以添加方法,當我需要他們。

class MyReflectionClass extends ReflectionClass 
{ 
    public function getAllMethodNamesExcept(array $excluded) 
    { 
     $methods = array_diff(
      get_class_methods($this->name), 
      $excluded 
     ); 
     return $methods; 
    } 
} 

你也可以使用不同的模擬框架來支持你想要做的事情。例如,Phake有一個thenCallParent方法。我最近開始使用Phake是因爲我需要能夠捕獲傳遞給方法的參數。它是有據可查的,值得一試。

相關問題