Тестовая вставка базы данных с использованием Symfony


Всем доброго дня,

В последние несколько дней я много занимался разработкой на основе тестов и решил, что мне тоже нужно этому научиться. Хотя я не могу понять, как это сделать точно.

Мой проект зависит от платформы и доктрины Symfony2.1.6, поэтому у меня есть несколько таблиц базы данных, которые необходимо заполнить.

Книга (1, n) - (0,n) Жанр

Теперь, если я хочу вставить жанровую запись, мне сначала нужно написать тест, чтобы убедиться, что все вставляется так, как должно (или я ошибаюсь?)

Проблема сейчас в том, что я не знаю, как получить доступ к своей базе данных, поскольку она управляется платформой.

Единственное, что я смог найти, это с помощью LiipFunctionalTestBundle https://github.com/liip/LiipFunctionalTestBundle , который создает и восстанавливает временную базу данных каждый раз, когда я запускаю тест. Я настроил все в соответствии с Инструкциями.

Редактировать: Мое приложение/конфигурация/config_test.yml выглядит вот так сейчас:

imports:
    - { resource: config_dev.yml }

framework:
    test: ~
    session:
        storage_id: session.storage.filesystem

liip_functional_test: ~

web_profiler:
    toolbar: false
    intercept_redirects: false

swiftmailer:
    disable_delivery: true

liip_functional_test:
    cache_sqlite_db: true

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   pdo_sqlite
                path:     %kernel.cache_dir%/test.db

Итак, теперь у меня есть класс GenreTest:
У Liip нет документации, поэтому я просто попробовал такой подход.

use Liip\FunctionalTestBundle\Test\WebTestCase;
class GenreTest extends WebTestCase {
    public function testInsert() {
        $container = $this->getContainer();
        $registry = $container->get('doctrine');
        $em = $registry->getEntityManager(null);       

        $genre = new Genre();
        $genre->setName("testGenre"); 

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

        $result = $em->createQuery("SELECT g FROM QkprodMangressBundle:Genre g ".
                                  "WHERE g.name = :name")
                    ->setParameter("name", $genre->getName())
                    ->getResult();

        $this->assertEqual($result[0]->getName(), $genre->getName());
    }
}

Веб-сайт Phpunit -c/

Исключение PDO: не удалось найти драйвер /.../Мангресс/поставщик/доктрина/dbal/библиотека/Доктрина/DBAL/Драйвер/pdoconnection.php:36 /.../Mangress/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php :60 /.../Мангресс/поставщик/доктрина/dbal/библиотека/Доктрина/DBAL/Подключение.php:350 /.../Мангресс/поставщик/доктрина/dbal/библиотека/Доктрина/DBAL/Подключение.php:949 /.../Мангресс/поставщик/доктрина/orm/библиотека/Доктрина/ORM/UnitOfWork.php:306 /.../Мангресс/поставщик/доктрина/orm/библиотека/Доктрина/ORM/EntityManager.php:355 /.../Мангресс/приложение/кэш/тест/jms_diextra/доктрина/entitymanager_510128d0a5878.ph р:362 /.../Mangress/src/Qkprod/Mangressbundle/Тесты/Сущность/genretest.php:27 НЕУДАЧИ! Тесты: 3, Утверждения: 1, Ошибки: 1.

Главный вопрос, который у меня возникает, заключается в том... как мне проверить что-то в этом роде? Или я даже проверяю связь с базой данных? Подделка связи с базой данных с помощью пользовательской реализации не кажется мне хорошей идеей, потому что она также будет использовать ORM и доктрину в производственной среде.

Извините.. здесь оказался небольшой роман.

Author: A.L, 2013-01-24

3 answers

Я почти полностью решил свою проблему с помощью:

  1. Установите драйверы, необходимые для связи с бд ;)
    Драйвер PDO_SQLITE отсутствует.. что делать?

    sudo apt-get install php5-sqlite
    
  2. Воссоздавайте схему при каждом запуске теста
    https://stackoverflow.com/a/10463614/1177024


Это тестирование моего класса по базе данных
namespace Qkprod\MangressBundle\Entity;

use Qkprod\MangressBundle\Entity\Genre;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

    private $em;

    /**
     * Sets up environment for testing
     * Regenerates Database schema before every test-run
     */
    public function setUp() {
        static::$kernel = static::createKernel();
        static::$kernel -> boot();
        $this -> em = static::$kernel->getContainer()
                                     ->get('doctrine')
                                     ->getEntityManager();
        $this->regenerateSchema();
    }

    protected function tearDown() {
        parent::tearDown();
        $this -> em -> close();
    }

    /**
     * Drops current schema and creates a brand new one
     */
    protected function regenerateSchema() {
        $metadatas = $this->em->getMetadataFactory()->getAllMetadata();
        if (!empty($metadatas)) {
            $tool = new \Doctrine\ORM\Tools\SchemaTool($this->em);
            $tool -> dropSchema($metadatas);
            $tool -> createSchema($metadatas);
        }
    }


    public function testInsert() {
        $genre = new Genre();
        $genre -> setName("testGenre");

        $this -> em -> persist($genre);
        $this -> em -> flush();

        $result = $this -> em 
                    -> createQuery("SELECT g "
                                 . " FROM QkprodMangressBundle:Genre g " 
                                 . " WHERE g.name = :name") 
                    -> setParameter("name", $genre -> getName())
                    -> getResult();

        $this -> assertEquals($result[0] -> getName(), $genre -> getName());
    }
}


Не удалось заставить LiipBundle работать, но вы можете увеличить невероятно ускорьте работу, настроив symfony для сохранения базы данных sqlite в памяти вместо файловой системы. https://stackoverflow.com/a/10460139/1177024

# app/config/config_test
doctrine:
    dbal:
        driver: pdo_sqlite
        path: :memory:
        memory: true


Или, может быть, создайте схему только один раз и вместо того, чтобы создавать ее заново, просто замените базу данных новой резервной копией.

Я надеюсь, что это сократит поиск некоторых людей, у которых такая же проблема! Спасибо всем, кто помогал мне на этом пути:) Ты великолепен!

 8
Author: Michael Kargl, 2017-05-23 11:59:08

Попробуйте еще раз с помощью документов symfony.

Http://symfony.com/doc/2.0/cookbook/testing/doctrine.html

Или вы можете изменить свой конструктор тестового набора с помощью:

public function __construct()
{
    $kernelNameClass = $this->getKernelClass();
    $kernel = new $kernelNameClass('test', true);
    $kernel->boot();
    $this->em = $kernel->getContainer()->get('doctrine.orm.entity_manager');
}

Затем вы будете использовать

$this->em->createQuery($dql);

И т.д.

 1
Author: Max Małecki, 2013-01-24 13:37:45

Вы можете подключиться внутри метода setUp():

/**
 * @var \Doctrine\ORM\EntityManager
 */
private $em;

/**
 * {@inheritDoc}
 */
public function setUp()
{
    static::$kernel = static::createKernel();
    static::$kernel->boot();
    $this->em = static::$kernel->getContainer()
        ->get('doctrine')
        ->getManager()
    ;
}

Здесь пример из книги Symfony 2.1

 1
Author: tttony, 2013-01-25 04:10:45