2013-07-29 63 views
1

我有這個類:如何部分使用嘲笑模擬一個類?

class PagSeguro { 

    public function pay() 
    { 
     if (! $this->checkAllData()) 
     { 
      return false; 
     } 

     return $this->buildPaymentURL(); 
    } 

    private function checkAllData() 
    { 
     return true; 
    } 

    private function buildPaymentURL() 
    { 
     echo "not cool!\n\n"; 

     return true; 
    } 

} 

而且這個測試吧:

public function testPagSeguroPaymentData() 
{ 
    $m = m::mock('PagSeguro[buildPaymentURL]'); 

    $m->shouldReceive('buildPaymentURL') 
     ->once() 
     ->andReturn('http://'); 

    $this->assertEquals($m->pay(), 'http://'); 
} 

如果我的var_dump($ M)我看到模擬的方法:

'buildPaymentURL' => 
    class Mockery\ExpectationDirector#1507 (5) { 
     protected $_name => 
     string(15) "buildPaymentURL" 
     protected $_mock => 
       ... 

     protected $_expectations => 
     array(1) { 
     ... 
     } 
     protected $_expectedOrder => 
     NULL 
     protected $_defaults => 
     array(0) { 
     ... 
     } 
    } 
    } 

但是當測試執行,它不是嘲弄的,而是真正的。除非我重命名它

private function buildPaymentURL_RENAMED() {} 

然後我得到一個綠色。

任何人都可以告訴我使用Mockery進行部分模擬的正確方法嗎?

回答

4

我認爲你不能讓該方法爲private,因爲當你輸入真實對象的代碼時,對$this->buildPaymentURL的任何調用都必須以真正的私有方法結束。

使其受到保護。這樣,模擬可以擴展你的類並覆蓋函數。

另一方面,如果需要這種部分模擬,我總會有一種不好的感覺。它們很可能是不良設計的標誌。看起來,這個私有方法應該被包含在它自己的一個對象中,它獨立地處理URL的創建(並且可以單獨進行測試),並且您現在正在測試的這個類應該只是獲得注入該新類的完整模擬。

+0

不得不公開它的工作,因爲受保護的行爲是一樣的。關於設計:這個類的全部目的實際上就是這個URL,還有其他一些方法可以將數據放在一起,但是「付款」部分是由這種方法制作的,這種方法稱爲外部庫,與支付服務通話PagSeguro)。但是,謝謝你的建議,無論如何都肯定有問題。 :) –

+1

好吧,如果它調用一個外部庫,嘲笑那個lib! – Sven

+0

太好了。會做的。再次感謝。 –