|
4 | 4 |
|
5 | 5 | namespace PhpList\Core\TestingSupport\Traits; |
6 | 6 |
|
| 7 | +use Doctrine\Common\DataFixtures\Purger\ORMPurger; |
7 | 8 | use Doctrine\ORM\EntityManagerInterface; |
| 9 | +use Doctrine\ORM\Tools\SchemaTool; |
| 10 | +use Doctrine\ORM\Tools\ToolsException; |
| 11 | +use InvalidArgumentException; |
8 | 12 | use PhpList\Core\Core\Bootstrap; |
9 | 13 | use PhpList\Core\Core\Environment; |
10 | | -use PHPUnit\DbUnit\Database\Connection; |
11 | | -use PHPUnit\DbUnit\DataSet\CsvDataSet; |
12 | | -use PHPUnit\DbUnit\Operation\Factory; |
13 | | -use PHPUnit\DbUnit\Operation\Operation; |
14 | | -use PHPUnit\DbUnit\TestCaseTrait; |
15 | | -use Symfony\Component\DependencyInjection\ContainerInterface; |
| 14 | +use RuntimeException; |
16 | 15 |
|
17 | 16 | /** |
18 | | - * This is a trait for integration tests that use database records. |
19 | | - * |
20 | | - * If you have your own setUp method, make sure to call $this->setUpDatabaseTest() first thing in your setUp method. |
21 | | - * |
22 | | - * And if you have your own tearDown method, call $this->tearDownDatabaseTest() first thing in your tearDown method. |
23 | | - * |
24 | | - * @author Oliver Klee <[email protected]> |
| 17 | + * This trait provides support for integration tests involving database records. |
25 | 18 | */ |
26 | 19 | trait DatabaseTestTrait |
27 | 20 | { |
28 | | - use TestCaseTrait; |
| 21 | + protected ?Bootstrap $bootstrap = null; |
| 22 | + protected ?EntityManagerInterface $entityManager = null; |
| 23 | + protected static $container; |
29 | 24 |
|
30 | 25 | /** |
31 | | - * @var Connection |
| 26 | + * Sets up the database test environment. |
32 | 27 | */ |
33 | | - private $databaseConnection = null; |
34 | | - |
35 | | - /** |
36 | | - * @var \PDO |
37 | | - */ |
38 | | - private static $pdo = null; |
39 | | - |
40 | | - /** |
41 | | - * @var CsvDataSet |
42 | | - */ |
43 | | - private $dataSet = null; |
44 | | - |
45 | | - /** |
46 | | - * @var Bootstrap |
47 | | - */ |
48 | | - protected $bootstrap = null; |
49 | | - |
50 | | - /** |
51 | | - * @var EntityManagerInterface |
52 | | - */ |
53 | | - protected $entityManager = null; |
54 | | - |
55 | | - /** |
56 | | - * @var ContainerInterface |
57 | | - */ |
58 | | - protected $container = null; |
59 | | - |
60 | | - protected function setUp() |
| 28 | + protected function setUpDatabaseTest(): void |
61 | 29 | { |
62 | | - $this->setUpDatabaseTest(); |
63 | | - } |
64 | | - |
65 | | - protected function setUpDatabaseTest() |
66 | | - { |
67 | | - $this->initializeDatabaseTester(); |
68 | | - $this->bootstrap = Bootstrap::getInstance()->setEnvironment(Environment::TESTING)->configure(); |
69 | | - $this->container = $this->bootstrap->getContainer(); |
70 | | - $this->entityManager = $this->bootstrap->getEntityManager(); |
71 | | - static::assertTrue($this->entityManager->isOpen()); |
| 30 | + $this->initializeBootstrap(); |
| 31 | + $this->clearDatabase(); |
72 | 32 | } |
73 | 33 |
|
74 | 34 | /** |
75 | | - * Initializes the CSV data set and the database tester. |
76 | | - * |
77 | | - * @return void |
| 35 | + * Tears down the database test environment. |
78 | 36 | */ |
79 | | - protected function initializeDatabaseTester() |
| 37 | + protected function tearDownDatabaseTest(): void |
80 | 38 | { |
81 | | - $this->dataSet = new CsvDataSet(); |
82 | | - |
83 | | - unset($this->databaseTester); |
84 | | - $this->getDatabaseTester()->setSetUpOperation($this->getSetUpOperation()); |
85 | | - } |
86 | | - |
87 | | - protected function tearDown() |
88 | | - { |
89 | | - $this->tearDownDatabaseTest(); |
| 39 | + $this->entityManager?->clear(); |
| 40 | + $this->entityManager?->close(); |
| 41 | + $this->bootstrap = null; |
| 42 | + $this->entityManager = null; |
90 | 43 | } |
91 | 44 |
|
92 | | - protected function tearDownDatabaseTest() |
| 45 | + /** |
| 46 | + * Initializes the Bootstrap and Doctrine EntityManager. |
| 47 | + */ |
| 48 | + private function initializeBootstrap(): void |
93 | 49 | { |
94 | | - $this->entityManager->close(); |
95 | | - $this->getDatabaseTester()->setTearDownOperation($this->getTearDownOperation()); |
96 | | - $this->getDatabaseTester()->setDataSet($this->getDataSet()); |
97 | | - $this->getDatabaseTester()->onTearDown(); |
| 50 | + $this->bootstrap = Bootstrap::getInstance() |
| 51 | + ->setEnvironment(Environment::TESTING) |
| 52 | + ->configure(); |
98 | 53 |
|
99 | | - // Destroy the tester after the test is run to keep DB connections |
100 | | - // from piling up. |
101 | | - unset($this->databaseTester); |
| 54 | + $this->entityManager = $this->bootstrap->getEntityManager(); |
102 | 55 |
|
103 | | - Bootstrap::purgeInstance(); |
| 56 | + if (!$this->entityManager->isOpen()) { |
| 57 | + throw new RuntimeException('The Doctrine EntityManager is not open.'); |
| 58 | + } |
104 | 59 | } |
105 | 60 |
|
106 | 61 | /** |
107 | | - * Returns the database operation executed in test cleanup. |
108 | | - * |
109 | | - * @return Operation |
| 62 | + * Clears the database using ORMPurger. |
110 | 63 | */ |
111 | | - protected function getTearDownOperation(): Operation |
| 64 | + private function clearDatabase(): void |
112 | 65 | { |
113 | | - return Factory::TRUNCATE(); |
| 66 | + if (!$this->entityManager) { |
| 67 | + throw new RuntimeException('EntityManager not initialized.'); |
| 68 | + } |
| 69 | + |
| 70 | + $purger = new ORMPurger($this->entityManager); |
| 71 | + $purger->purge(); |
114 | 72 | } |
115 | 73 |
|
116 | 74 | /** |
117 | | - * Returns the test database connection. |
| 75 | + * Loads data fixtures into the database. |
118 | 76 | * |
119 | | - * @return Connection |
| 77 | + * @param array $fixtures List of fixture classes to load |
120 | 78 | */ |
121 | | - protected function getConnection(): Connection |
| 79 | + protected function loadFixtures(array $fixtures): void |
122 | 80 | { |
123 | | - if ($this->databaseConnection === null) { |
124 | | - if (self::$pdo === null) { |
125 | | - $databaseHost = getenv('PHPLIST_DATABASE_HOST') ?: 'localhost'; |
126 | | - $databasePort = getenv('PHPLIST_DATABASE_PORT') ?: '3306'; |
127 | | - $databaseName = getenv('PHPLIST_DATABASE_NAME'); |
128 | | - self::$pdo = new \PDO( |
129 | | - 'mysql:host='.$databaseHost.';port='.$databasePort.';dbname='.$databaseName, |
130 | | - getenv('PHPLIST_DATABASE_USER'), |
131 | | - getenv('PHPLIST_DATABASE_PASSWORD') |
132 | | - ); |
| 81 | + foreach ($fixtures as $fixture) { |
| 82 | + $fixtureInstance = new $fixture(); |
| 83 | + if (!method_exists($fixtureInstance, 'load')) { |
| 84 | + throw new InvalidArgumentException(sprintf('Fixture %s must have a load() method.', $fixture)); |
133 | 85 | } |
134 | | - $this->databaseConnection = $this->createDefaultDBConnection(self::$pdo); |
| 86 | + |
| 87 | + $fixtureInstance->load($this->entityManager); |
135 | 88 | } |
136 | 89 |
|
137 | | - return $this->databaseConnection; |
| 90 | + $this->entityManager->flush(); |
138 | 91 | } |
139 | 92 |
|
140 | | - /** |
141 | | - * Returns the test data set. |
142 | | - * |
143 | | - * Add data to in the individual test by calling $this->getDataSet()->addTable. |
144 | | - * |
145 | | - * @return CsvDataSet |
146 | | - */ |
147 | | - protected function getDataSet(): CsvDataSet |
| 93 | + protected function loadSchema(): void |
148 | 94 | { |
149 | | - return $this->dataSet; |
150 | | - } |
| 95 | + $this->entityManager = self::getContainer()->get('doctrine.orm.entity_manager'); |
| 96 | + $schemaTool = new SchemaTool($this->entityManager); |
| 97 | + $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata(); |
151 | 98 |
|
152 | | - /** |
153 | | - * Applies all database changes on $this->dataSet. |
154 | | - * |
155 | | - * This methods needs to be called after the last addTable call in each test. |
156 | | - * |
157 | | - * @return void |
158 | | - */ |
159 | | - protected function applyDatabaseChanges() |
160 | | - { |
161 | | - $this->getDatabaseTester()->setDataSet($this->getDataSet()); |
162 | | - $this->getDatabaseTester()->onSetUp(); |
163 | | - } |
| 99 | + $connection = $this->entityManager->getConnection(); |
| 100 | + $schemaManager = $connection->createSchemaManager(); |
164 | 101 |
|
165 | | - /** |
166 | | - * Marks the table with the given name as "touched", i.e., it will be truncated in the tearDown method. |
167 | | - * |
168 | | - * This is useful if the table gets populated only by the tested code instead of by using the addTable |
169 | | - * and applyDatabaseChanges method. |
170 | | - * |
171 | | - * @param string $tableName |
172 | | - * |
173 | | - * @return void |
174 | | - */ |
175 | | - protected function touchDatabaseTable(string $tableName) |
176 | | - { |
177 | | - $this->getDataSet()->addTable($tableName, __DIR__ . '/../Fixtures/TouchTable.csv'); |
| 102 | + foreach ($metadata as $classMetadata) { |
| 103 | + $tableName = $classMetadata->getTableName(); |
| 104 | + |
| 105 | + if (!$schemaManager->tablesExist([$tableName])) { |
| 106 | + try { |
| 107 | + $schemaTool->createSchema([$classMetadata]); |
| 108 | + } catch (ToolsException $e){} |
| 109 | + } |
| 110 | + } |
178 | 111 | } |
179 | 112 | } |
0 commit comments