Passed
Pull Request — master (#278)
by Asmir
03:32
created

php$0 ➔ testCustomConnection()   A

Complexity

Conditions 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
rs 9.6333
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 sys_get_temp_dir;
29
30
class DoctrineMigrationsExtensionTest extends TestCase
31
{
32
    public function testXmlConfigs() : void
33
    {
34
        $container = $this->getContainer();
35
36
        $conn = $this->createMock(Connection::class);
37
        $container->set('doctrine.dbal.default_connection', $conn);
38
39
        $container->registerExtension(new DoctrineMigrationsExtension());
40
        $container->setAlias('doctrine.migrations.configuration.test', new Alias('doctrine.migrations.configuration', true));
41
42
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Fixtures'));
43
        $loader->load('conf.xml');
44
45
        $container->compile();
46
47
        $config = $container->get('doctrine.migrations.configuration.test');
48
        $this->assertConfigs($config);
49
    }
50
51
    public function testFullConfig() : void
52
    {
53
        $container = $this->getContainer();
54
        $extension = new DoctrineMigrationsExtension();
55
56
        $config = [
57
            'name' => 'Doctrine Sandbox Migrations',
58
            'storage' => [
59
                'table_storage' => [
60
                    'table_name'                 => 'doctrine_migration_versions_test',
61
                    'version_column_name'        => 'doctrine_migration_column_test',
62
                    'version_column_length'      => 2000,
63
                    'executed_at_column_name'    => 'doctrine_migration_executed_at_column_test',
64
                    'execution_time_column_name' => 'doctrine_migration_execution_time_column_test',
65
                ],
66
            ],
67
68
            'migrations_paths' => [
69
                'DoctrineMigrationsTest' => 'a',
70
                'DoctrineMigrationsTest2' => 'b',
71
            ],
72
73
            'migrations' => ['Foo', 'Bar'],
74
75
            'organize_migrations' => 'BY_YEAR_AND_MONTH',
76
77
            'all_or_nothing'            => true,
78
            'check_database_platform'   => true,
79
        ];
80
81
        $conn = $this->createMock(Connection::class);
82
        $container->set('doctrine.dbal.default_connection', $conn);
83
84
        $extension->load(['doctrine_migrations' => $config], $container);
85
86
        $container->getDefinition('doctrine.migrations.configuration')->setPublic(true);
87
        $container->compile();
88
89
        $config = $container->get('doctrine.migrations.configuration');
90
91
        $this->assertConfigs($config);
92
    }
93
94
    private function assertConfigs(?object $config) : void
95
    {
96
        self::assertInstanceOf(Configuration::class, $config);
97
        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

97
        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...
98
        self::assertSame([
99
            'DoctrineMigrationsTest' => 'a',
100
            'DoctrineMigrationsTest2' => 'b',
101
102
        ], $config->getMigrationDirectories());
103
104
        self::assertSame(['Foo', 'Bar'], $config->getMigrationClasses());
105
        self::assertTrue($config->isAllOrNothing());
106
        self::assertTrue($config->isDatabasePlatformChecked());
107
        self::assertTrue($config->areMigrationsOrganizedByYearAndMonth());
108
109
        $storage = $config->getMetadataStorageConfiguration();
110
        self::assertInstanceOf(TableMetadataStorageConfiguration::class, $storage);
111
112
        self::assertSame('doctrine_migration_versions_test', $storage->getTableName());
113
        self::assertSame('doctrine_migration_column_test', $storage->getVersionColumnName());
114
        self::assertSame(2000, $storage->getVersionColumnLength());
115
        self::assertSame('doctrine_migration_execution_time_column_test', $storage->getExecutionTimeColumnName());
116
        self::assertSame('doctrine_migration_executed_at_column_test', $storage->getExecutedAtColumnName());
117
    }
118
119
    public function testCustomSorter() : void
120
    {
121
        $container = $this->getContainer();
122
        $extension = new DoctrineMigrationsExtension();
123
124
        $config = [
125
            'services' => [Comparator::class => 'my_sorter'],
126
        ];
127
128
        $extension->load(['doctrine_migrations' => $config], $container);
129
130
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
131
132
        $conn = $this->createMock(Connection::class);
133
        $container->set('doctrine.dbal.default_connection', $conn);
134
135
        $sorter = new class() implements Comparator{
136
            public function compare(Version $a, Version $b) : int
137
            {
138
            }
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...
139
        };
140
        $container->set('my_sorter', $sorter);
141
142
        $container->compile();
143
144
        $di = $container->get('doctrine.migrations.dependency_factory');
145
        self::assertInstanceOf(DependencyFactory::class, $di);
146
        self::assertSame($sorter, $di->getVersionComparator());
147
    }
148
149
    public function testCustomConnection() : void
150
    {
151
        $container = $this->getContainer();
152
        $extension = new DoctrineMigrationsExtension();
153
154
        $config = ['connection' => 'custom'];
155
156
        $extension->load(['doctrine_migrations' => $config], $container);
157
158
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
159
160
        $conn = $this->createMock(Connection::class);
161
        $container->set('doctrine.dbal.custom_connection', $conn);
162
163
        $container->compile();
164
165
        $di = $container->get('doctrine.migrations.dependency_factory');
166
        self::assertInstanceOf(DependencyFactory::class, $di);
167
        self::assertSame($conn, $di->getConnection());
168
    }
169
170
171
    public function testPrefersEntityManagerOverConnection() : void
172
    {
173
        $container = $this->getContainer();
174
        $extension = new DoctrineMigrationsExtension();
175
176
        $em = $this->createMock(EntityManager::class);
177
        $container->set('doctrine.orm.default_entity_manager', $em);
178
179
        $extension->load(['doctrine_migrations' => []], $container);
180
181
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
182
183
        $container->compile();
184
185
        $di = $container->get('doctrine.migrations.dependency_factory');
186
187
        self::assertInstanceOf(DependencyFactory::class, $di);
188
        self::assertSame($em, $di->getEntityManager());
189
    }
190
191
    public function testCustomEntityManager() : void
192
    {
193
        $container = $this->getContainer();
194
        $extension = new DoctrineMigrationsExtension();
195
196
        $config = ['em' => 'custom'];
197
198
        $em = new Definition(CustomEntityManager::class);
199
        $container->setDefinition('doctrine.orm.custom_entity_manager', $em);
200
201
        $extension->load(['doctrine_migrations' => $config], $container);
202
203
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
204
205
        $container->compile();
206
207
        $di = $container->get('doctrine.migrations.dependency_factory');
208
        self::assertInstanceOf(DependencyFactory::class, $di);
209
210
        $em = $di->getEntityManager();
211
        self::assertInstanceOf(CustomEntityManager::class, $em);
212
213
        assert(method_exists($di->getConnection(), 'getEm'));
214
        self::assertInstanceOf(CustomEntityManager::class, $di->getConnection()->getEm());
215
        self::assertSame($em, $di->getConnection()->getEm());
216
    }
217
218
    public function testCustomMetadataStorage() : void
219
    {
220
        $container = $this->getContainer();
221
        $extension = new DoctrineMigrationsExtension();
222
223
        $config = [
224
            'services' => [MetadataStorage::class => 'mock_storage_service'],
225
        ];
226
227
        $mockStorage = $this->createMock(MetadataStorage::class);
228
        $container->set('mock_storage_service', $mockStorage);
229
230
        $conn = $this->createMock(Connection::class);
231
        $container->set('doctrine.dbal.default_connection', $conn);
232
233
        $extension->load(['doctrine_migrations' => $config], $container);
234
235
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
236
237
        $container->compile();
238
239
        $di = $container->get('doctrine.migrations.dependency_factory');
240
        self::assertInstanceOf(DependencyFactory::class, $di);
241
        self::assertSame($mockStorage, $di->getMetadataStorage());
242
    }
243
244
    public function testInvalidService() : void
245
    {
246
        $this->expectException(InvalidConfigurationException::class);
247
        $this->expectExceptionMessage('Invalid configuration for path "doctrine_migrations.services": Valid services for the DoctrineMigrationsBundle must be in the "Doctrine\Migrations" namespace.');
248
        $container = $this->getContainer();
249
        $extension = new DoctrineMigrationsExtension();
250
251
        $config = [
252
            'services' => ['foo' => 'mock_storage_service'],
253
        ];
254
255
        $conn = $this->createMock(Connection::class);
256
        $container->set('doctrine.dbal.default_connection', $conn);
257
258
        $extension->load(['doctrine_migrations' => $config], $container);
259
260
        $container->compile();
261
    }
262
263
    public function testCanNotSpecifyBothEmAndConnection() : void
264
    {
265
        $this->expectExceptionMessage('You cannot specify both "connection" and "em" in the DoctrineMigrationsBundle configurations');
266
        $this->expectException(InvalidArgumentException::class);
267
        $container = $this->getContainer();
268
        $extension = new DoctrineMigrationsExtension();
269
270
        $config = [
271
            'em' => 'custom',
272
            'connection' => 'custom',
273
        ];
274
275
        $extension->load(['doctrine_migrations' => $config], $container);
276
277
        $container->getDefinition('doctrine.migrations.dependency_factory')->setPublic(true);
278
279
        $container->compile();
280
    }
281
282
    private function getContainer() : ContainerBuilder
283
    {
284
        return new ContainerBuilder(new ParameterBag([
285
            'kernel.debug' => false,
286
            'kernel.bundles' => [],
287
            'kernel.cache_dir' => sys_get_temp_dir(),
288
            'kernel.environment' => 'test',
289
            'kernel.project_dir' => __DIR__ . '/../',
290
        ]));
291
    }
292
}
293