2

So I'm working on some tests where I need to create fixtures data.

Basically I used to have the following pseudo code that worked fine:

public function setUp()
{
    // Programmatically create a coupon code
}

// Test methods

public function tearDown()
{
    // Programmatically delete the coupon code
}

On Vinai's recommendation, and to make my test easier to manage I decided to change that code to the following so I don't have to manually delete my fixture data anymore:

public function setUp()
{
    Mage::getSingleton('core/resource')->getConnection('core_write')->beginTransaction();
    // Programmatically create a coupon code
}

// Test methods

public function tearDown()
{
    Mage::getSingleton('core/resource')->getConnection('core_write')->rollBack();
}

However, with this code, my tests don't run properly anymore and I get the Zend_Db_Statement_Exception: SQLSTATE[23000]: Integrity constraint violation errors.

I was wondering if that's the right way of using transaction ?

Is the following order the right one ?

  • begin transaction
  • make DB changes (create DB data, and call the save() method)
  • rollback transaction

Do I need to call commit() before rollBack() ?

Raphael at Digital Pianism
  • 70,385
  • 34
  • 188
  • 352

1 Answers1

4

I would have to see the code you are using. All DB operations that do not change the structure of tables (so no DDL methods) are allowed in a transaction.

All I can offer is the following example of a test that utilizes a transaction to isolate the database changes.

<?php

namespace Example;

class SomeTestWithATransaction extends \PHPUnit_Framework_TestCase
{
    /**
     * @return \Varien_Db_Adapter_Interface
     */
    private function getConnection()
    {
        /** @var \Mage_Core_Model_Resource $resource */
        $resource = \Mage::getSingleton('core/resource');
        return $resource->getConnection('default_write');
    }

    /**
     * @param string $sku
     * @return \Mage_Catalog_Model_Product
     */
    private function createProduct($sku)
    {
        $prevStore = \Mage::app()->getStore();
        \Mage::app()->setCurrentStore(\Mage_Core_Model_Store::ADMIN_CODE);
        $product = $this->instantiateProductModel($sku);
        $product->save();
        \Mage::app()->setCurrentStore($prevStore->getCode());

        return $product;
    }

    /**
     * @param string $sku
     * @return \Mage_Catalog_Model_Product
     */
    private function instantiateProductModel($sku)
    {
        /** @var \Mage_Catalog_Model_Product $product */
        $product = \Mage::getModel('catalog/product');
        $product->setData([
            'sku'              => $sku,
            'name'             => 'Test Product ' . $sku,
            'price'            => '1.0',
            'weight'           => '1',
            'type_id'          => \Mage_Catalog_Model_Product_Type::TYPE_SIMPLE,
            'attribute_set_id' => $this->getAttributeSetId(),
            'website_ids'      => array_keys(\Mage::app()->getWebsites()),
        ]);
        $this->addTestStockItemToProduct($product);
        return $product;
    }

    /**
     * @return string
     */
    private function getAttributeSetId()
    {
        /** @var \Mage_Eav_Model_Config $eavConfig */
        $eavConfig = \Mage::getSingleton('eav/config');
        $productEntityType = $eavConfig->getEntityType(\Mage_Catalog_Model_Product::ENTITY);
        return $productEntityType->getDefaultAttributeSetId();
    }

    private function addTestStockItemToProduct(\Mage_Catalog_Model_Product $product)
    {
        /** @var \Mage_CatalogInventory_Model_Stock_Item $stockItem */
        $stockItem = \Mage::getModel('cataloginventory/stock_item');
        $stockItem->setQty(1000);
        $stockItem->setIsInStock(1);
        $product->setData('stock_item', $stockItem);
    }

    protected function setUp()
    {
        $this->getConnection()->beginTransaction();
        \Mage::app()->loadArea(\Mage_Core_Model_App_Area::AREA_FRONTEND);
    }

    protected function tearDown()
    {
        $this->getConnection()->rollBack();

        \Mage::reset();
    }

    public function testUpdatesTheProductInTheDatabase()
    {
        \Mage::app()->setCurrentStore(\Mage_Core_Model_Store::ADMIN_CODE);

        $product = $this->createProduct('foo');
        $id = $product->getId();
        $product->setData('sku', 'bar');
        $product->save();

        /** @var \Mage_Catalog_Model_Product $product2 */
        $product2 = \Mage::getModel('catalog/product');
        $product2->load($id);

        $this->assertSame('bar', $product2->getSku());
    }

}
Raphael at Digital Pianism
  • 70,385
  • 34
  • 188
  • 352
Vinai
  • 14,014
  • 2
  • 42
  • 83