packages/sql-fixture/tests/Unit/Provider/FixtureGeneratorTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Provider;
6
7use Faker\Factory;
8use PHPUnit\Framework\Attributes\CoversClass;
9use PHPUnit\Framework\Attributes\Test;
10use PHPUnit\Framework\Attributes\UsesClass;
11use PHPUnit\Framework\TestCase;
12use SqlFixture\Fixture\Exception\InvalidOverrideException;
13use SqlFixture\Hydrator\ReflectionHydrator;
14use SqlFixture\Platform\MySql\MySqlSchemaParser;
15use SqlFixture\Platform\MySql\MySqlTypeMapper;
16use SqlFixture\Provider\FixtureGenerator;
17use SqlFixture\Schema\ColumnDefinition;
18use SqlFixture\Schema\TableSchema;
19
20#[CoversClass(FixtureGenerator::class)]
21#[UsesClass(InvalidOverrideException::class)]
22#[UsesClass(MySqlTypeMapper::class)]
23#[UsesClass(ColumnDefinition::class)]
24#[UsesClass(TableSchema::class)]
25#[UsesClass(ReflectionHydrator::class)]
26#[CoversClass(\SqlFixture\Fixture\Validation\OverrideValidator::class)]
27#[UsesClass(\SqlFixture\Hydrator\HydrationException::class)]
28#[UsesClass(\SqlFixture\Hydrator\HydratorInterface::class)]
29#[UsesClass(MySqlSchemaParser::class)]
30#[UsesClass(\SqlFixture\Schema\SchemaParseException::class)]
31#[UsesClass(\SqlFixture\Schema\SchemaParserInterface::class)]
32#[UsesClass(\SqlFixture\TypeMapper\TypeMapperInterface::class)]
33#[UsesClass(\SqlFixture\Fixture\RowGeneration::class)]
34#[UsesClass(\SqlFixture\Hydrator\Reflection\ConstructorHydration::class)]
35#[UsesClass(\SqlFixture\Hydrator\Reflection\PropertyHydration::class)]
36#[UsesClass(\SqlFixture\Hydrator\Reflection\PropertyNames::class)]
37#[UsesClass(\SqlFixture\Hydrator\Reflection\ValueConversion::class)]
38#[UsesClass(\SqlFixture\Platform\MySql\Schema\ColumnParser::class)]
39#[UsesClass(\SqlFixture\Platform\MySql\Schema\DefaultExpression::class)]
40#[UsesClass(\SqlFixture\Platform\MySql\Schema\DefinitionIntegrity::class)]
41#[UsesClass(\SqlFixture\Platform\MySql\Schema\TableDefinition::class)]
42#[UsesClass(\SqlFixture\Platform\MySql\Schema\TypeParameters::class)]
43#[UsesClass(\SqlFixture\Platform\MySql\Value\ColumnGenerator::class)]
44#[UsesClass(\SqlFixture\Platform\MySql\Value\DecimalGenerator::class)]
45#[UsesClass(\SqlFixture\Platform\MySql\Value\GeometryGenerator::class)]
46#[UsesClass(\SqlFixture\Platform\MySql\Value\IntegerGenerator::class)]
47#[UsesClass(\SqlFixture\Platform\MySql\Value\NumericGenerator::class)]
48#[UsesClass(\SqlFixture\Platform\MySql\Value\SpatialGenerator::class)]
49#[UsesClass(\SqlFixture\Platform\MySql\Value\StringGenerator::class)]
50#[UsesClass(\SqlFixture\Platform\MySql\Value\TextGenerator::class)]
51#[UsesClass(\SqlFixture\Schema\TypeShape::class)]
52#[UsesClass(\SqlFixture\TypeMapper\ParagraphGenerator::class)]
53#[UsesClass(\SqlFixture\Platform\MySql\Schema\TableDefinitionInput::class)]
54#[UsesClass(\SqlFixture\Hydrator\Exception\ClassNotFoundException::class)]
55#[UsesClass(\SqlFixture\Hydrator\Exception\MissingConstructorArgumentException::class)]
56#[UsesClass(\SqlFixture\Fixture\Exception\UnknownOverrideColumnException::class)]
57#[UsesClass(\SqlFixture\Fixture\Exception\NullOverrideException::class)]
58#[UsesClass(\SqlFixture\Fixture\Exception\GeneratedColumnOverrideException::class)]
59#[UsesClass(\SqlFixture\Schema\Exception\InvalidSqlException::class)]
60#[UsesClass(\SqlFixture\Schema\Exception\ExpectedCreateTableException::class)]
61#[UsesClass(\SqlFixture\Schema\Exception\MissingColumnDefinitionsException::class)]
62#[UsesClass(\SqlFixture\TypeMapper\IntegerRange::class)]
63#[UsesClass(\SqlFixture\TypeMapper\IntegerWidth::class)]
64#[UsesClass(\SqlFixture\TypeMapper\DecimalRange::class)]
65#[UsesClass(\SqlFixture\Hydrator\Reflection\ConversionTarget::class)]
66#[UsesClass(\SqlFixture\Fixture\RowGenerator::class)]
67final class FixtureGeneratorTest extends TestCase
68{
69 #[Test]
70 public function testGenerateWithSchema(): void
71 {
72 $schema = new TableSchema('users', [
73 'id' => new ColumnDefinition('id', 'INT'),
74 'name' => new ColumnDefinition('name', 'VARCHAR', length: 255),
75 ], ['id']);
76
77 $faker = Factory::create();
78 $faker->seed(12345);
79 $data = (new FixtureGenerator($faker))->generate($schema);
80
81 self::assertArrayHasKey('id', $data);
82 self::assertArrayHasKey('name', $data);
83 }
84
85 #[Test]
86 public function testGenerateWithOverrides(): void
87 {
88 $schema = new TableSchema('users', [
89 'id' => new ColumnDefinition('id', 'INT'),
90 'name' => new ColumnDefinition('name', 'VARCHAR', length: 255),
91 ], ['id']);
92
93 $faker = Factory::create();
94 $faker->seed(12345);
95 $data = (new FixtureGenerator($faker))->generate($schema, ['name' => 'Override']);
96
97 self::assertSame('Override', $data['name']);
98 }
99
100 #[Test]
101 public function testGenerateSkipsAutoIncrement(): void
102 {
103 $schema = new TableSchema('users', [
104 'id' => new ColumnDefinition('id', 'INT', autoIncrement: true),
105 'name' => new ColumnDefinition('name', 'VARCHAR', length: 255),
106 ], ['id']);
107
108 $faker = Factory::create();
109 $faker->seed(12345);
110 $data = (new FixtureGenerator($faker))->generate($schema);
111
112 self::assertArrayNotHasKey('id', $data);
113 self::assertArrayHasKey('name', $data);
114 self::assertIsString($data['name']);
115 }
116
117 #[Test]
118 public function testGenerateSkipsGeneratedColumns(): void
119 {
120 $schema = new TableSchema('users', [
121 'id' => new ColumnDefinition('id', 'INT'),
122 'computed' => new ColumnDefinition('computed', 'INT', generated: true),
123 'name' => new ColumnDefinition('name', 'VARCHAR', length: 255),
124 ], ['id']);
125
126 $faker = Factory::create();
127 $faker->seed(12345);
128 $data = (new FixtureGenerator($faker))->generate($schema);
129
130 self::assertArrayNotHasKey('computed', $data);
131 self::assertArrayHasKey('id', $data);
132 self::assertArrayHasKey('name', $data);
133 }
134
135 #[Test]
136 public function testGenerateWithHydration(): void
137 {
138 $target = new class (0, '') {
139 public function __construct(
140 public readonly int $id,
141 public readonly string $name,
142 ) {
143 }
144 };
145 $schema = new TableSchema('users', [
146 'id' => new ColumnDefinition('id', 'INT'),
147 'name' => new ColumnDefinition('name', 'VARCHAR', length: 255),
148 ], ['id']);
149
150 $faker = Factory::create();
151 $faker->seed(12345);
152 $user = (new FixtureGenerator($faker))->generate($schema, ['id' => 1, 'name' => 'Test'], $target::class);
153
154 self::assertSame(1, $user->id);
155 self::assertSame('Test', $user->name);
156 }
157
158 #[Test]
159 public function testGetSchemaParser(): void
160 {
161 $faker = Factory::create();
162 $faker->seed(12345);
163 $parser = (new FixtureGenerator($faker))->getSchemaParser();
164 self::assertInstanceOf(MySqlSchemaParser::class, $parser);
165 }
166
167 #[Test]
168 public function testGetTypeMapper(): void
169 {
170 $faker = Factory::create();
171 $faker->seed(12345);
172 $mapper = (new FixtureGenerator($faker))->getTypeMapper();
173 self::assertInstanceOf(MySqlTypeMapper::class, $mapper);
174 }
175
176 #[Test]
177 public function testGetHydrator(): void
178 {
179 $faker = Factory::create();
180 $faker->seed(12345);
181 $hydrator = (new FixtureGenerator($faker))->getHydrator();
182 self::assertInstanceOf(ReflectionHydrator::class, $hydrator);
183 }
184
185 #[Test]
186 public function testConfigureWithCustomDependencies(): void
187 {
188 $faker = Factory::create();
189 $customMapper = new MySqlTypeMapper();
190 $customHydrator = new ReflectionHydrator();
191 $customParser = new MySqlSchemaParser();
192
193 $generator = new FixtureGenerator(
194 $faker,
195 $customMapper,
196 $customHydrator,
197 $customParser
198 );
199
200 self::assertSame($customMapper, $generator->getTypeMapper());
201 self::assertSame($customHydrator, $generator->getHydrator());
202 self::assertSame($customParser, $generator->getSchemaParser());
203 }
204
205 #[Test]
206 public function testNullIsAcceptedForANullableColumn(): void
207 {
208 $schema = new TableSchema('users', [
209 'note' => new ColumnDefinition('note', 'VARCHAR', length: 255, nullable: true),
210 ]);
211
212 $data = (new FixtureGenerator(Factory::create()))->generate($schema, ['note' => null]);
213
214 self::assertNull($data['note']);
215 }
216
217 #[Test]
218 public function testAnOverrideForAnAutoIncrementColumnIsStillAllowed(): void
219 {
220 $schema = new TableSchema('users', [
221 'id' => new ColumnDefinition('id', 'INT', autoIncrement: true),
222 ], ['id']);
223
224 $data = (new FixtureGenerator(Factory::create()))->generate($schema, ['id' => 100]);
225
226 self::assertSame(100, $data['id']);
227 }
228}
229