2017-05-15 67 views
0

我正在測試發送到模擬事件處理程序的參數。該參數是「事件」子類型的對象,它本身具有嵌套在其中的一些數據。我想測試事件,並且它的子結構通過各種模擬匹配我已經注入到代碼中的夾具數據。如何在PHPUnit模擬調用期望中聲明參數屬性子結構

我可以很容易地測試事件的「頂層」:類名和簡單的屬性,如事件名稱字符串。我也可以測試一個屬性包含相同的對象,我相信它隱式地測試了對象的所有子結構。

我遇到的問題是一些更復雜的例子中的子結構導致測試失敗,但它是無關緊要的,所以我想選擇子結構的特定屬性,以及不只是身份 - 比較整個對象。

我覺得我在屬性斷言中缺少一些東西:如何訪問「with」引用的參數 - 作爲變量。然後我可以將它傳遞給一些assert方法,比如attributeEqualTo,這些方法要求被測試的項目被傳入。也許這些不能在我使用的流暢的情況下使用?

  • 我想檢查event.data是一個特定的類。
  • 我想檢查event.data.thing1 == X
  • 我想檢查event.data.thing2 == Y 等等。

簡化代碼:

class MyEventData{ 
    public $thing1; 
    public $thing2; 
} 

class MyEvent{ 
    public $data; 
} 

// An event gets fired containing this in the tests 
$eventData = new MyEventData(1,2); 

$this->eventMock->expects($this->exactly(3)) 
    ->method('fire') 
    ->with(
     $this->logicalAnd(
     // THIS WORKS OK 
      $this->isInstanceOf('\MyApp\MyEvents\SomeEvent'), 
      // THIS WORKS OK 
      $this->attributeEqualTo ('name', SomeEvent::EVENT_NAME),  
      // THIS WORKS in simplified cases only 
      $this->attributeEqualTo ('data', $eventData), 

      // HOW DO I GET THE "WITH" PARAMETER CONTEXT "INTO" THE THIRD PARAMETER? 
      $this->assertAttributeInstanceOf('\MyApp\MyEvents\MyEventData', 'data', -classOrObject-), 

      // Then how can I test with attribute data.thing1 == 1 and data.thing2 = 2 

     ) 
    ); 
+0

哪個對象/類是您的測試目標?如果你測試事件處理程序,那麼你不應該模擬測試類 –

+0

@AdamW。我沒有顯示目標S.U.T.爲簡單起見。事件模擬是從它接收呼叫的許多注入子系統之一。 – scipilot

回答

0

我知道了使用callback約束工作,但感覺就像我現在已經走下通道,失去的PHPUnit的力量 - 我可以」似乎已經在這裏使用斷言助手了。

例如如果累計測試返回錯誤,我不會在輸出日誌中看到「期望失敗......並被指定回調接受」的詳細信息。

$this->callback(function($subject){ 
     $b = true; 
     // I tried using this constraint but can't access (autoload) this class? So is it not supposed to be used directly? 
     //$c = new PHPUnit_Framework_Constraint_IsInstanceOf('\MyApp\MyEvents\MyEventData'); 
     // return $c->matches(subject); 

     // this is the right assert, but it doesn't return the result, so I cannot use it in a callback constraint. 
     \PHPUnit_Framework_Assert::assertAttributeInstanceOf('\MyApp\MyEvents\MyEventData', 'data', $subject); 

     // This works but seems very "Manual" 
     $b = $b && get_class($subject->data) == '\MyApp\MyEvents\MyEventData'; 
     $b = $b && $subject->data->thing1 == 1; 
     $b = $b && $subject->data->thing2 == 1; 
     return $b; 
    })