2012-04-04 75 views
5

我想用Symfony2,Doctrine和MongoDB構建一套安全的測試。Symfony2 Doctrine MongoDB rollback

我需要做的是在測試開始時加載很多燈具,並在測試結束後卸載它們。我想用交易做到這一點,但是......我找不到有關如何使用Doctrine和Mongo做到的文檔!

我在Doctrine文檔中發現了good documentation關於如何與ORM進行交易,但不涉及ODM。

所以我看了看使用的原則,蒙戈太source code of the Connection.php類,我還沒有發現dbal version使用beginTransactioncommitrollback方法。

我是一無所知,然後我問自己「它甚至有可能在MongoDB中回滾?」,如果在MongoDB FAQ找到了答案是:

的MongoDB不使用傳統的鎖定或複雜的交易回滾

:(所以我想這就是爲什麼沒有在ODM沒有beginTransaction或任何...

但我的問題仍然是:我怎麼能imple爲我的測試回滾一種?

我現在唯一的想法是手動獲取我加載的文檔的所有ID,然後在tearDown()中刪除它們。但是,呃...它有點糟糕,不是嗎?

其他想法?

編輯: 我第一次到這個問題的意見後,關於我想有同樣的分貝測試和開發的事實,我想:爲什麼不使用單獨的測試數據庫,其中開發數據庫在測試開始時被複制,並且可以輕鬆地刪除?

難道這是個好主意嗎?它實際上對我來說看起來更簡單,更安全。你們有什麼感想?

謝謝:)

+0

我忘了說,我沒有使用兩個單獨的數據塊進行開發和測試,因此普通的'拆解()'那滴一切不是我一個解決方案... – mokagio 2012-04-04 14:07:32

回答

4
我不是用於開發兩個單獨的DB和測試

這是解決的第一件事

- 因爲沒有一個測試分貝,運行測試會影響你的發展分貝反之亦然這是一個可怕的想法。您應該能夠在生產環境中運行測試,絕對相信您在測試中做的任何事情都不會影響您部署的站點。

安裝測試連接

因此,修改parameters.yml有這樣的事情:

database.host: localhost 
database.port: 27017 
database.db: myappname 

database.test.host: localhost 
database.test.port: 27017 
database.test.db: myappname-test 

此外,在您的應用程序/配置/ config_test.yml文件覆蓋默認連接,以便您作爲測試的一部分觸發任何請求默認文檔管理器的內容,將會收到一個指向您的測試分區的管理器:

doctrine_mongodb: 
    document_managers: 
     default: 
      database: %database.test.db% 

與燈具

然後,你要有效地做準備測試是:

  • 截斷相關藏品
  • 負載燈具在每個測試之前,你的測試數據庫

下面是一個例子抽象測試類:

<?php 

use Doctrine\Common\DataFixtures\Executor\MongoDBExecutor as Executor, 
    Doctrine\Common\DataFixtures\Purger\MongoDBPurger as Purger, 
    Doctrine\Common\DataFixtures\Loader, 
    Doctrine\Common\DataFixtures\ReferenceRepository, 
    Symfony\Bundle\FrameworkBundle\Test\WebTestCase, 
    Symfony\Bundle\FrameworkBundle\Console\Application; 

abstract class AbstractTest extends WebTestCase 
{ 
    /** 
    * Array of fixtures to load. 
    */ 
    protected $fixtures = array(); 

    /** 
    * Setup test environment 
    */ 
    public function setUp() 
    { 
     $kernel = static::createKernel(array('environment' => 'test', 'debug' => false)); 
     $kernel->boot(); 
     $this->container = $kernel->getContainer(); 
     $this->dm = $this->container->get('doctrine.odm.mongodb.document_manager'); 

     if ($this->fixtures) { 
      $this->loadFixtures($this->fixtures, false); 
     } 
    } 

    /** 
    * Load fixtures 
    * 
    * @param array $fixtures names of _fixtures to load 
    * @param boolean $append append data, or replace? 
    */ 
    protected function loadFixtures($fixtures = array(), $append = true) 
    { 
     $defaultFixtures = false; 

     $loader = new Loader(); 
     $refRepo = new ReferenceRepository($this->dm); 

     foreach ((array) $fixtures as $name) { 
      $fixture = new $name(); 
      $fixture->setReferenceRepository($refRepo); 
      $loader->addFixture($fixture); 
     } 

     $purger = new Purger(); 
     $executor = new Executor($this->dm, $purger); 
     $executor->execute($loader->getFixtures(), $append); 
    } 
} 

使用固定裝置在你的測試

與以往的抽象測試類,然後你可以寫一個使用固定數據進行測試 - 或不 - 作爲適當的。下面是一個簡單的例子。

<?php 

use Your\AbstractTest, 
    Your\Document\Foo; 

class RandomTest extends AbstractTest 
{ 
    /** 
    * fixtures to load before each test 
    */ 
    protected $fixtures = array(
     'APP\FooBundle\DataFixtures\MongoDB\TestFoos', 
     'APP\FooBundle\DataFixtures\MongoDB\TestBars' 
    ); 

    ... 

    /** 
    * Check it gets an ID (insert succeeded) 
    * 
    */ 
    public function testCreateDefaults() 
    { 
     $foo = new Foo(); 
     $this->dm->persist($foo); 
     $this->dm->flush(); 

     $this->assertNotNull($foo->getId()); 
     $this->assertSame('default value', $foo->getSomeProperty()); 
     // etc. 
    } 

    /** 
    * Check result of something with a given input 
    * 
    */ 
    public function testSomething() 
    { 
     $foo = $this->dm->getRepository(APPFooBundle:Foo)->findByName('Some fixture object'); 

     $foo->doSomething(); 
     $this->assertSame('modified value', $foo->getSomeProperty()); 
     // etc. 
    } 

每次測試之前,您已經定義了燈具將被加載(截斷他們影響的集合),從而在其基礎上的測試一致的數據庫狀態。

+0

這種做法正是我一直在尋找(和後來在我的腦海裏有我的最後一次編輯) 我同意你的事實,具有相同的數據庫是一個非常糟糕的主意。這是東西「強加」給我,但我能在最後:) – mokagio 2012-04-10 12:56:34

+0

這是一個非常酷的解決方案來改變它。不幸的是,這隻適用於你不需要在你的燈具中的容器意識。通過API加載容器感知裝置根本不起作用,導致錯誤,凍結和其他問題。 – Tom 2013-02-22 14:25:21

+0

集裝箱意識應該不會影響使用測試數據庫連接是否正常工作 - 如果它聽起來像是你有一些隱含的(數據)的依賴,你是不滿足引起循環,錯誤和一般混亂。在可能的情況下 - 夾具文件應該像岩石一樣笨拙。 – AD7six 2013-02-22 14:55:54

1

每次測試之前剛落,你的MongoDB數據庫,然後加載你需要的燈具。這樣每個測試都將完全隔離。

+0

,而我是編輯和添加這個你回答選項的問題。 :) – mokagio 2012-04-04 14:22:42