1

getModelMock()とreplaceByMock('model'、$ model_path、$ mock)を正常に使用しました。今日、私はこのコードを再利用して「保存」をオーバーライドしようとしましたが、機能しませんでした。少し掘り下げた後、モデルがモックされていない理由の違いがわかりました。

モックを正常に使用すると、コードは新しいモデルで開始されます。

$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->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);

また、以下を使用してリソースモデルを試しました。

$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);

コードをステップスルーした後、リソースモデルをモックする必要があるのではないかと思いました。それは機能せず、モデルとリソースモデルの両方をモックすることもできませんでした。私がテストしようとしているのは、$ model-> save()を使用して既存のモデルのデータを更新しようとしたときにキャッチされる例外です。

4

3 に答える 3

0

では、モックしたいモデルはテスト対象のコンポーネントでもありますか?私はそれを変えようとします。

私がテストしようとしているのは、$ model-> save()を使用して既存のモデルのデータを更新しようとしたときにキャッチされる例外です。

正しいことを理解したかどうかはわかりませんが(テストコードが役立つでしょう)、リソースモデルをモックすることは一般的に良い考えのようです。これにより、データベースから独立してテストを実行することもできます。

あなたの出発点:

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

私はあなたの「例外がキャッチされた」と文字通り受け取り、リソースモデルがあなたのモデルがキャッチすべき例外をスローすると仮定したことに注意してください。しかし、私はあなたが本当に「投げられた」ことを意味したのではないかと疑っています。その場合、モックは代わりに有効なものを返す必要があります。

于 2013-03-22T17:42:25.657 に答える
0

モックを成功させる方法が見つからなかったので、これは回避策です。この「保存」例外を実際にテストするよりも、コードカバレッジについて心配しています。とにかく、コードカバレッジを分析するときにphpunitに無視するように指示する以下のコメントで実際のコードをラップしました。

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

私はそれをごまかしたくないのですが、コードはかなり単純なので、私は本当に心配していません。

于 2013-04-25T15:05:24.463 に答える
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);
}

}

于 2014-12-05T15:24:45.523 に答える