Doctrine orm 在每次测试后,不使用数据固定装置,对数据库条目执行Nuke/Delete/Truncate操作

Doctrine orm 在每次测试后,不使用数据固定装置,对数据库条目执行Nuke/Delete/Truncate操作,doctrine-orm,phpunit,symfony-3.4,Doctrine Orm,Phpunit,Symfony 3.4,我有以下测试用例: namespace Tests\AppBundle\Repository; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use AppBundle\Entity\ContactEmail; class ContactEmailTest extends KernelTestCase { /** * @var \Doctrine\ORM\EntityManager */ privat

我有以下测试用例:

namespace Tests\AppBundle\Repository;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use AppBundle\Entity\ContactEmail;

class ContactEmailTest extends KernelTestCase
{
  /**
    * @var \Doctrine\ORM\EntityManager
    */
   private $entityManager;

   /**
    * {@inheritDoc}
    */
   protected function setUp()
   {
       $kernel = self::bootKernel();

       $this->entityManager = $kernel->getContainer()
           ->get('doctrine')
           ->getManager();
   }


   public function testInsert()
   {
     $email="jdoe@example.com";
     /**
     * @var Appbundle\Repository\ContactEmailRepository
     */
     $repository=$this->entityManager->getRepository(ContactEmail::class);

     $contactEmailEntity=$repository->addEmail($email);
     $this->assertEquals($contactEmailEntity->getEmail(),$email);

     $emailSearched=$repository->findByEmail($email);

     if(empty($emailSearched)){
        $this->fail('No email has been found');
     }

     $this->assertEquals($email,$emailSearched[0]);
   }


   /**
   * expectException(Doctrine\DBAL\Exception\UniqueConstraintViolationException)
   */
   public function testInsertDucplicate()
   {
     $email="jdoe@example.com";
     /**
     * @var Appbundle\Repository\ContactEmailRepository
     */
     $repository=$this->entityManager->getRepository(ContactEmail::class);

     // We purpocely ingoring the returned value
     $repository->addEmail($email);
     $repository->addEmail($email);

   }

    /**
     * {@inheritDoc}
     */
    protected function tearDown()
    {
        parent::tearDown();

        $this->entityManager->close();
        $this->entityManager = null; // avoid memory leaks
    }
}
我尝试测试自定义存储库的以下方法:

namespace AppBundle\Repository;

use AppBundle\Entity\ContactEmail;

/**
 * ContactEmailRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class ContactEmailRepository extends \Doctrine\ORM\EntityRepository
{
  /**
  * Adding an Email to the database
  * @param String $email
  *
  * @throws Doctrine\DBAL\Exception\UniqueConstraintViolationException
  *
  * @return AppBundle\Entity\ContactEmail
  */
  public function addEmail($email)
  {
      $emailToAdd=new ContactEmail();
      $emailToAdd->setEmail($email);

      /**
      * @var Doctrine\ORM\EntityManager
      */
      $em=$this->getEntityManager();

      $em->persist($emailToAdd);
      $em->flush();

      return $emailToAdd;
  }
}
那么,在每次测试之后,我将如何核化所有数据库条目,以便拥有一个干净实例的新的空数据库呢


我之所以这么问,是因为我不想让以前的测试留下的条目破坏我的测试。

一个好办法是使用这个网络中提到的逻辑。为此,将
设置方法更改为:

   //namespace definition and use classes from other namespaces

   use Doctrine\ORM\Tools\SchemaTool;

   //Class definition etc etc...

   protected function setUp()
   {
       $kernel = self::bootKernel();

       $this->entityManager = $kernel->getContainer()
           ->get('doctrine')
           ->getManager();

       //In case leftover entries exist
       $schemaTool = new SchemaTool($this->entityManager);
       $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata();

       // Drop and recreate tables for all entities
       $schemaTool->dropSchema($metadata);
       $schemaTool->createSchema($metadata);
   }
如您所见,您可以通过
$this->entityManager->getMetadataFactory()->getAllMetadata()获取模式信息链方法调用,然后使用chematool以编程方式清除和创建模式

另外一个好方法是为测试使用单独的数据库。在我的例子中,我将以下配置放入
config test.yml

doctrine:
    dbal:
      dbname: '%database_name%-test'

这会自动在数据库名称后面添加一个
-test
结尾,这样,如果我开发的数据库名为
mydb
,那么测试数据库将是
mydb test
,这样你就可以随心所欲地执行测试,而不用担心破坏开发工作流程。

也许我在你的代码中漏掉了一些应该做的东西让它对我来说更明显,但我很好奇为什么你想要避免使用数据装置?我不是在避免它,只是在我的测试用例中,我不需要数据装置。如果您更仔细地观察,您将看到我测试了数据插入,因此不需要数据装置。我只是放置了数据夹具参考,以便将我的问题与其他问题区分开来。您可以在
setUp()
tearDown()
或两者上重置数据库。例如,让快照文件系统重置数据库。