Skip to content

Commit b5fe9e1

Browse files
committed
ISSUE-337: fixture test fix
1 parent 07d93a5 commit b5fe9e1

20 files changed

+518
-594
lines changed

config/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ doctrine:
5252
auto_mapping: true
5353
mappings:
5454
PhpList\Core\Domain\Model:
55-
type: annotation
5655
is_bundle: false
57-
prefix: PhpList\Core\Domain\Model
56+
type: attribute
5857
dir: '%kernel.project_dir%/src/Domain/Model/'
58+
prefix: 'PhpList\Core\Domain\Model\'

config/config_test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@ framework:
77
storage_id: session.storage.mock_file
88
profiler:
99
collect: false
10+
11+
doctrine:
12+
dbal:
13+
driver: 'pdo_sqlite'
14+
memory: true
15+
charset: UTF8

src/Domain/Model/Identity/Administrator.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,12 @@ public function setSuperUser(bool $superUser): void
114114
{
115115
$this->superUser = $superUser;
116116
}
117+
118+
#[ORM\PrePersist]
119+
public function setCreationDate(): void
120+
{
121+
if ($this->creationDate === null) {
122+
$this->creationDate = new DateTime();
123+
}
124+
}
117125
}

src/Domain/Model/Identity/AdministratorToken.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public function generateKey(): void
103103
$this->setKey($key);
104104
}
105105

106-
public function getAdministrator(): ?Administrator
106+
public function getAdministrator(): Administrator|Proxy|null
107107
{
108108
return $this->administrator;
109109
}

src/Domain/Model/Traits/IdentityTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ trait IdentityTrait
2020
#[ORM\Column(type: "integer")]
2121
#[ORM\GeneratedValue]
2222
#[SerializedName("id")]
23-
private int $id = 0;
23+
private int $id;
2424

2525
public function getId(): int
2626
{
Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,35 @@
11
<?php
2+
23
declare(strict_types=1);
34

45
namespace PhpList\Core\TestingSupport;
56

67
use PhpList\Core\Core\Bootstrap;
78
use PhpList\Core\Core\Environment;
8-
use Symfony\Bundle\FrameworkBundle\Client;
9+
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
910
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
1011

1112
/**
1213
* Base class for integration tests for controllers.
1314
*
1415
* If you have your own setUp method, make sure to call $this->setUpWebTest() first thing in your setUp method.
15-
*
16-
* @author Oliver Klee <[email protected]>
1716
*/
1817
abstract class AbstractWebTest extends WebTestCase
1918
{
20-
/**
21-
* @var Client
22-
*/
23-
protected $client = null;
19+
protected ?KernelBrowser $client = null;
2420

25-
protected function setUp()
21+
protected function setUp(): void
2622
{
23+
parent::setUp();
2724
$this->setUpWebTest();
2825
}
2926

30-
protected function setUpWebTest()
27+
protected function setUpWebTest(): void
3128
{
32-
// This makes sure that all DateTime instances use the same time zone, thus making the dates in the
33-
// JSON provided by the REST API easier to test.
3429
date_default_timezone_set('UTC');
3530

3631
Bootstrap::getInstance()->setEnvironment(Environment::TESTING)->configure();
3732

38-
$this->client = static::createClient(['environment' => Environment::TESTING]);
33+
$this->client = static::createClient();
3934
}
4035
}

src/TestingSupport/Traits/ContainsInstanceAssertionTrait.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
declare(strict_types=1);
34

45
namespace PhpList\Core\TestingSupport\Traits;
@@ -17,11 +18,11 @@ trait ContainsInstanceAssertionTrait
1718
*
1819
* @return void
1920
*/
20-
public static function assertContainsInstanceOf(string $className, array $haystack, string $message = '')
21+
public static function assertContainsInstanceOf(string $className, array $haystack, string $message = ''): void
2122
{
2223
$found = false;
2324
foreach ($haystack as $element) {
24-
if (is_object($element) && $element instanceof $className) {
25+
if ($element instanceof $className) {
2526
$found = true;
2627
break;
2728
}

src/TestingSupport/Traits/DatabaseTestTrait.php

Lines changed: 63 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -4,176 +4,109 @@
44

55
namespace PhpList\Core\TestingSupport\Traits;
66

7+
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
78
use Doctrine\ORM\EntityManagerInterface;
9+
use Doctrine\ORM\Tools\SchemaTool;
10+
use Doctrine\ORM\Tools\ToolsException;
11+
use InvalidArgumentException;
812
use PhpList\Core\Core\Bootstrap;
913
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;
1615

1716
/**
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.
2518
*/
2619
trait DatabaseTestTrait
2720
{
28-
use TestCaseTrait;
21+
protected ?Bootstrap $bootstrap = null;
22+
protected ?EntityManagerInterface $entityManager = null;
23+
protected static $container;
2924

3025
/**
31-
* @var Connection
26+
* Sets up the database test environment.
3227
*/
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
6129
{
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();
7232
}
7333

7434
/**
75-
* Initializes the CSV data set and the database tester.
76-
*
77-
* @return void
35+
* Tears down the database test environment.
7836
*/
79-
protected function initializeDatabaseTester()
37+
protected function tearDownDatabaseTest(): void
8038
{
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;
9043
}
9144

92-
protected function tearDownDatabaseTest()
45+
/**
46+
* Initializes the Bootstrap and Doctrine EntityManager.
47+
*/
48+
private function initializeBootstrap(): void
9349
{
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();
9853

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();
10255

103-
Bootstrap::purgeInstance();
56+
if (!$this->entityManager->isOpen()) {
57+
throw new RuntimeException('The Doctrine EntityManager is not open.');
58+
}
10459
}
10560

10661
/**
107-
* Returns the database operation executed in test cleanup.
108-
*
109-
* @return Operation
62+
* Clears the database using ORMPurger.
11063
*/
111-
protected function getTearDownOperation(): Operation
64+
private function clearDatabase(): void
11265
{
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();
11472
}
11573

11674
/**
117-
* Returns the test database connection.
75+
* Loads data fixtures into the database.
11876
*
119-
* @return Connection
77+
* @param array $fixtures List of fixture classes to load
12078
*/
121-
protected function getConnection(): Connection
79+
protected function loadFixtures(array $fixtures): void
12280
{
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));
13385
}
134-
$this->databaseConnection = $this->createDefaultDBConnection(self::$pdo);
86+
87+
$fixtureInstance->load($this->entityManager);
13588
}
13689

137-
return $this->databaseConnection;
90+
$this->entityManager->flush();
13891
}
13992

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
14894
{
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();
15198

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();
164101

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+
}
178111
}
179112
}

0 commit comments

Comments
 (0)