Nuke/Delete/Truncate 每次测试后不使用数据固定装置的数据库条目

Nuke/Delete/Truncate Database entries after each test WITHOUT the use of data fixtures

我有以下测试用例:

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;
  }
}

那么在每次测试之后,我如何核对所有数据库条目,以便拥有一个带有干净实例的全新空数据库?

我问这个问题的原因是因为我不想让以前的测试留下的条目可能会破坏我的测试。

一个很好的做法是使用此网络中 中提到的逻辑。为此,将 setUp 方法更改为:

   //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,因此您可以执行您的随心所欲地进行测试,而不必担心破坏开发工作流程。