2013-03-22 79 views
1

我已經成功地使用getModelMock()和replaceByMock( '模型',$ model_path,$模擬)。今天我試圖重複使用這段代碼來覆蓋「保存」,但它不起作用。經過一番挖掘,我現在看到了爲什麼模型沒有被嘲笑的區別。EcomDev_PHPUnit模擬Magento的模型集合

當使用模擬成功我的代碼開始一個新的模式:

$model = Mage::getModel('test/model'); 
$model->setData('field', 'value'); 
$model->save(); //this gets mocked 

沒有正在嘲笑我加載使用收集的記錄的代碼。簡化:

$model = Mage::getModel('test/model')->getCollection()->getFirstItem(); 
$model->setData('field', 'value'); 
$model->save(); //this does NOT get mocked 

在這兩種情況下,我用下面的代碼來模擬模型:

$mock = $this->getResourceModelMock('test/model', array('save')); 

    $mock->expects($this->once()) 
     ->method('save') 
     ->will($this->returnCallBack(function(){throw new Exception('Mock error');}) 
     ); 

    $this->replaceByMock('resource_model', 'test/model', $mock); 

通過步進後:

$mock = $this->getModelMock('test/model', array('save')); 

    $mock->expects($this->once()) 
     ->method('save') 
     ->will($this->returnCallBack(function(){throw new Exception('Mock error');}) 
     ); 

    $this->replaceByMock('model', 'test/model', $mock); 

我也使用下面的嘗試資源模型代碼我想也許我只需要嘲笑資源模型。這不起作用,也沒有嘲笑模型和資源模型。要更新使用$模型 - >保存在現有的模型數據,當我試圖測試是被捕獲的異常()。

回答

0

我找不到如何獲得成功的模擬,所以這是一個變通。我更擔心代碼覆蓋率,而不是實際測試這個「保存」異常。無論如何,我剛剛結束與下面告訴PHPUnit的分析代碼覆蓋率時忽略它的評論的實際代碼:

// @codeCoverageIgnoreStart 
[code goes here] 
// @codeCoverageIgnoreEnd 

我寧願不要做傻事,但代碼是非常簡單的,所以我真的不擔心。

0

所以要嘲笑模式也試驗下的部件?我會盡力改變這一點。

我想要測試的是在使用$ model-> save()嘗試更新現有模型上的數據時被捕獲的異常。

不知道我是否理解正確的(測試代碼會有所幫助),但它看起來像嘲笑資源模型通常是一個好主意。這也使您能夠獨立於數據庫運行測試。

你的出發點:

$resourceModelMock = $this->getResourceModelMock('test/model'); 
$resourceModelMock->expects($this->once()) 
    ->method('save') 
    ->will($this->throwException(...)); 
$this->replaceByMock('resource_model', 'test/model', $resourceModelMock); 

請注意,我把你的「異常被抓」的字面和假設資源模型將拋出一個異常,你的模型應該。不過,我懷疑你的意思是「拋出」。在這種情況下,你的模擬應該返回一些有效的東西。

+0

模型是不是測試下一個組成部分,如果我正確理解你。你發佈的內容正是我嘗試沒有任何運氣。要複製我所看到的,試着模擬模型上的「保存」方法。在你的測試中,使用類似於我的第二個片段的集合加載該模型的現有對象。如果你更新對象並保存它,應該按照正常的含義進行,不會被嘲弄。只是重新迭代,如果我從一個新的模型對象開始,一切都如預期一樣嘲弄。 – gwgeller 2013-03-22 19:12:19

+0

我在原始示例中添加了更多內容。 – gwgeller 2013-03-22 20:12:02

0

您可以註冊爲收集資源的額外模擬。 而且每個集合項目將成爲模仿對象。

下面是小例子:

class YourCompany_YourModule_Test_Model_CatalogProduct extends EcomDev_PHPUnit_Test_Case { 

/** 
* Create product model mock and replace `getCollection` method with callback 
* 
* @return $this 
* @throws PHPUnit_Framework_Exception 
*/ 
protected function _registerProductStub() 
{ 
    $productModelMock = $this->getModelMock('catalog/product', array('getPrice', 'getCollection')); 
    $productModelMock->expects($this->any())->method('getPrice')->will($this->returnCallback(array($this, 'callbackGetTestValue'))); 
    $productModelMock->expects($this->any())->method('getCollection')->will($this->returnCallback(array($this, 'callbackGetCollection'))); 
    $this->replaceByMock('model', 'catalog/product', $productModelMock); 

    return $this; 
} 

/** 
* Create a product collection resource model with Mock and replace `getNewEmptyItem` method with callback 
* 
* @return $this 
* @throws PHPUnit_Framework_Exception 
*/ 
protected function _registerProductCollectionStub() 
{ 
    $productModelMockModelCollectionMock = $this->getResourceModelMock('catalog/product_collection', array('getNewEmptyItem')); 
    $productModelMockModelCollectionMock->expects($this->any())->method('getNewEmptyItem')->will($this->returnCallback(array($this, 'callbackGetNewEmptyItem'))); 
    $this->replaceByMock('resource_model', 'catalog/product_collection', $productModelMockModelCollectionMock); 

    return $this; 
} 

/** 
* Magento EAV checks that class of object is the same with predefined $this->_itemObjectClass 
* So we need to replace it too. 
*/ 
public function callbackGetCollection() 
{ 
    $model = Mage::getModel('catalog/product'); 
    $collection = $model->getResourceCollection(); 
    $collection->setItemObjectClass(get_class($model)); 
    $collection->getSelect()->limit(10); 
    return $collection; 
} 

/** 
* We change a default functionality and 
* new empty object calling will return a mock object 
* in place of straight creating object trough `new ClassName`. 
* Magento will automatically add data to this object from your fixture or database. 
* 
* @return Mage_Catalog_Model_Product 
*/ 
public function callbackGetNewEmptyItem() 
{ 
    return Mage::getModel('catalog/product'); 
} 

public function callbackGetTestValue() 
{ 
    return 99.99; 
} 

/** 
* @test 
*/ 
public function test_productModelIsMock() 
{ 
    $this->_registerProductStub() 
     ->_registerProductCollectionStub(); 

    $mockedProduct = Mage::getModel('catalog/product'); 
    $mockedProductFromCollection = Mage::getModel('catalog/product')->getCollection()->getFirstItem(); 

    $this->assertEquals(get_class($mockedProduct), get_class($mockedProductFromCollection)); 

    $this->assertEquals($mockedProduct->getPrice(), $mockedProductFromCollection->getPrice()); 
    $this->assertEquals($mockedProduct->getPrice(), 99.99); 
} 

}