Completed
Pull Request — master (#278)
by Asmir
06:07
created

php$0 ➔ testCustomEntityManager()   A

Complexity

Conditions 1

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 28
rs 9.472
cc 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Bundle\MigrationsBundle\Tests\DependencyInjection;
6
7
use Doctrine\Bundle\MigrationsBundle\DependencyInjection\DoctrineMigrationsExtension;
8
use Doctrine\Bundle\MigrationsBundle\Tests\Fixtures\CustomEntityManager;
9
use Doctrine\DBAL\Connection;
10
use Doctrine\Migrations\Configuration\Configuration;
11
use Doctrine\Migrations\DependencyFactory;
12
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
13
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
14
use Doctrine\Migrations\Version\Comparator;
15
use Doctrine\Migrations\Version\Version;
16
use Doctrine\ORM\EntityManager;
17
use InvalidArgumentException;
18
use PHPUnit\Framework\TestCase;
19
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
20
use Symfony\Component\Config\FileLocator;
21
use Symfony\Component\DependencyInjection\Alias;
22
use Symfony\Component\DependencyInjection\ContainerBuilder;
23
use Symfony\Component\DependencyInjection\Definition;
24
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
25
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
26
use function assert;
27
use function method_exists;
28
use function print_r;
29
use function sys_get_temp_dir;
30
31
class DoctrineMigrationsExtensionTest extends TestCase
32
{
33
    public function testXmlConfigs() : void
34
    {
35
        $container = $this->getContainer();
36
37
        $conn = $this->createMock(Connection::class);
38
        $container->set('doctrine.dbal.default_connection', $conn);
39
40
        $container->registerExtension(new DoctrineMigrationsExtension());
41
        $container->setAlias('doctrine.migrations.configuration.test', new Alias('doctrine.migrations.configuration', true));
42
43
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Fixtures'));
44
        $loader->load('conf.xml');
45
46
        $container->compile();
47
48
        $config = $container->get('doctrine.migrations.configuration.test');
49
        $this->assertConfigs($config);
50
    }
51
52
    public function testFullConfig() : void
53
    {
54
        $container = $this->getContainer();
55
        $extension = new DoctrineMigrationsExtension();
56
57
        $config = [
58
            'name' => 'Doctrine Sandbox Migrations',
59
            'storage' => [
60
                'table_storage' => [
61
                    'table_name'                 => 'doctrine_migration_versions_test',
62
                    'version_column_name'        => 'doctrine_migration_column_test',
63
                    'version_column_length'      => 2000,
64
                    'executed_at_column_name'    => 'doctrine_migration_executed_at_column_test',
65
                    'execution_time_column_name' => 'doctrine_migration_execution_time_column_test',
66
                ],
67
            ],
68
69
            'migrations_paths' => [
70
                'DoctrineMigrationsTest' => 'a',
71
                'DoctrineMigrationsTest2' => 'b',
72
            ],
73
74
            'migrations' => ['Foo', 'Bar'],
75
76
            'organize_migrations' => 'BY_YEAR_AND_MONTH',
77
78
            'all_or_nothing'            => true,
79
            'check_database_platform'   => true,
80
        ];
81
82
        $conn = $this->createMock(Connection::class);
83
        $container->set('doctrine.dbal.default_connection', $conn);
84
85
        $extension->load(['doctrine_migrations' => $config], $container);
86
87
        $container->getDefinition('doctrine.migrations.configuration')->setPublic(true);
88
        $container->compile();
89
90
        $config = $container->get('doctrine.migrations.configuration');
91
92
        $this->assertConfigs($config);
93
    }
94
95
    public function testNoConfig() : void
96
    {
97
        $this->expectException(InvalidConfigurationException::class);
98
        $this->expectExceptionMessage('The child node "migrations_paths" at path "doctrine_migrations" must be configured.');
99
100
        $container = $this->getContainer();
101
        $extension = new DoctrineMigrationsExtension();
102
103
        $conn = $this->createMock(Connection::class);
104
        $container->set('doctrine.dbal.default_connection', $conn);
105
106
        $extension->load([], $container);
107
108
        $container->getDefinition('doctrine.migrations.configuration')->setPublic(true);
109
        $container->compile();
110
111
        $config = $container->get('doctrine.migrations.configuration');
112
113
        print_r($config);
114
    }
115
116
117
    private function assertConfigs(?object $config) : void
118
    {
119
        self::assertInstanceOf(Configuration::class, $config);
120
        self::assertSame('Doctrine Sandbox Migrations', $config->getName());
0 ignored issues
show
Bug introduced by
The method getName() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
        self::assertSame('Doctrine Sandbox Migrations', $config->/** @scrutinizer ignore-call */ getName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
121
        self::assertSame([
122
            'DoctrineMigrationsTest' => 'a',
123
            'DoctrineMigrationsTest2' => 'b',
124
125
        ], $config->getMigrationDirectories());
126
127
        self::assertSame(['Foo', 'Bar'], $config->getMigrationClasses());
128
        self::assertTrue($config->isAllOrNothing());
129
        self::assertTrue($config->isDatabasePlatformChecked());
130
        self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
131
132
        $storage = $config->getMetadataStorageConfiguration();
133
        self::assertInstanceOf(TableMetadataStorageConfiguration::class, $storage);
134
135
        self::assertSame('doctrine_migration_versions_test', $storage->getTableName());
136
        self::assertSame('doctrine_migration_column_test', $storage->getVersionColumnName());
137
        self::assertSame(2000, $storage->getVersionColumnLength());
138
        self::assertSame('doctrine_migration_execution_time_column_test', $storage->getExecutionTimeColumnName());
139
        self::assertSame('doctrine_migration_executed_at_column_test', $storage->getExecutedAtColumnName());
140
    }
141
142
    public function testCustomSorter() : void
143
    {
144
        $container = $this->getContainer();
145
        $extension = new DoctrineMigrationsExtension();
146
147
        $config = [
148
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
149
            'services' => [Comparator::class => 'my_sorter'],
150
        ];
151
152
        $extension->load(['doctrine_migrations' => $config], $container);
153
154
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
155
156
        $conn = $this->createMock(Connection::class);
157
        $container->set('doctrine.dbal.default_connection', $conn);
158
159
        $sorter = new class() implements Comparator{
160
            public function compare(Version $a, Version $b) : int
161
            {
162
            }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return integer. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
163
        };
164
        $container->set('my_sorter', $sorter);
165
166
        $container->compile();
167
168
        $di = $container->get('doctrine.migrations.dependency_factory');
169
        self::assertInstanceOf(DependencyFactory::class, $di);
170
        self::assertSame($sorter, $di->getVersionComparator());
171
    }
172
173
    public function testCustomConnection() : void
174
    {
175
        $container = $this->getContainer();
176
        $extension = new DoctrineMigrationsExtension();
177
178
        $config = [
179
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
180
            'connection' => 'custom',
181
        ];
182
183
        $extension->load(['doctrine_migrations' => $config], $container);
184
185
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
186
187
        $conn = $this->createMock(Connection::class);
188
        $container->set('doctrine.dbal.custom_connection', $conn);
189
190
        $container->compile();
191
192
        $di = $container->get('doctrine.migrations.dependency_factory');
193
        self::assertInstanceOf(DependencyFactory::class, $di);
194
        self::assertSame($conn, $di->getConnection());
195
    }
196
197
198
    public function testPrefersEntityManagerOverConnection() : void
199
    {
200
        $container = $this->getContainer();
201
        $extension = new DoctrineMigrationsExtension();
202
203
        $em = $this->createMock(EntityManager::class);
204
        $container->set('doctrine.orm.default_entity_manager', $em);
205
206
        $extension->load([
207
            'doctrine_migrations' => [
208
                'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
209
            ],
210
        ], $container);
211
212
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
213
214
        $container->compile();
215
216
        $di = $container->get('doctrine.migrations.dependency_factory');
217
218
        self::assertInstanceOf(DependencyFactory::class, $di);
219
        self::assertSame($em, $di->getEntityManager());
220
    }
221
222
    public function testCustomEntityManager() : void
223
    {
224
        $container = $this->getContainer();
225
        $extension = new DoctrineMigrationsExtension();
226
227
        $config = [
228
            'em' => 'custom',
229
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
230
        ];
231
232
        $em = new Definition(CustomEntityManager::class);
233
        $container->setDefinition('doctrine.orm.custom_entity_manager', $em);
234
235
        $extension->load(['doctrine_migrations' => $config], $container);
236
237
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
238
239
        $container->compile();
240
241
        $di = $container->get('doctrine.migrations.dependency_factory');
242
        self::assertInstanceOf(DependencyFactory::class, $di);
243
244
        $em = $di->getEntityManager();
245
        self::assertInstanceOf(CustomEntityManager::class, $em);
246
247
        assert(method_exists($di->getConnection(), 'getEm'));
248
        self::assertInstanceOf(CustomEntityManager::class, $di->getConnection()->getEm());
249
        self::assertSame($em, $di->getConnection()->getEm());
250
    }
251
252
    public function testCustomMetadataStorage() : void
253
    {
254
        $container = $this->getContainer();
255
        $extension = new DoctrineMigrationsExtension();
256
257
        $config = [
258
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
259
            'services' => [MetadataStorage::class => 'mock_storage_service'],
260
        ];
261
262
        $mockStorage = $this->createMock(MetadataStorage::class);
263
        $container->set('mock_storage_service', $mockStorage);
264
265
        $conn = $this->createMock(Connection::class);
266
        $container->set('doctrine.dbal.default_connection', $conn);
267
268
        $extension->load(['doctrine_migrations' => $config], $container);
269
270
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
271
272
        $container->compile();
273
274
        $di = $container->get('doctrine.migrations.dependency_factory');
275
        self::assertInstanceOf(DependencyFactory::class, $di);
276
        self::assertSame($mockStorage, $di->getMetadataStorage());
277
    }
278
279
    public function testInvalidService() : void
280
    {
281
        $this->expectException(InvalidConfigurationException::class);
282
        $this->expectExceptionMessage('Invalid configuration for path "doctrine_migrations.services": Valid services for the DoctrineMigrationsBundle must be in the "Doctrine\Migrations" namespace.');
283
        $container = $this->getContainer();
284
        $extension = new DoctrineMigrationsExtension();
285
286
        $config = [
287
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
288
            'services' => ['foo' => 'mock_storage_service'],
289
        ];
290
291
        $conn = $this->createMock(Connection::class);
292
        $container->set('doctrine.dbal.default_connection', $conn);
293
294
        $extension->load(['doctrine_migrations' => $config], $container);
295
296
        $container->compile();
297
    }
298
299
    public function testCanNotSpecifyBothEmAndConnection() : void
300
    {
301
        $this->expectExceptionMessage('You cannot specify both "connection" and "em" in the DoctrineMigrationsBundle configurations');
302
        $this->expectException(InvalidArgumentException::class);
303
        $container = $this->getContainer();
304
        $extension = new DoctrineMigrationsExtension();
305
306
        $config = [
307
            'migrations_paths' => ['DoctrineMigrationsTest' => 'a'],
308
            'em' => 'custom',
309
            'connection' => 'custom',
310
        ];
311
312
        $extension->load(['doctrine_migrations' => $config], $container);
313
314
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
315
316
        $container->compile();
317
    }
318
319
    private function getContainer() : ContainerBuilder
320
    {
321
        return new ContainerBuilder(new ParameterBag([
322
            'kernel.debug' => false,
323
            'kernel.bundles' => [],
324
            'kernel.cache_dir' => sys_get_temp_dir(),
325
            'kernel.environment' => 'test',
326
            'kernel.project_dir' => __DIR__ . '/../',
327
        ]));
328
    }
329
}
330