Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
InstallerTest.php
Go to the documentation of this file.
1 <?php
8 
21  use Magento\Setup\Validator\DbValidator;
22 
27  class InstallerTest extends \PHPUnit\Framework\TestCase
28  {
32  private $object;
33 
37  private $filePermissions;
38 
42  private $configWriter;
43 
47  private $configReader;
48 
52  private $config;
53 
57  private $moduleList;
58 
62  private $moduleLoader;
63 
67  private $directoryList;
68 
72  private $adminFactory;
73 
77  private $logger;
78 
82  private $random;
83 
87  private $connection;
88 
92  private $maintenanceMode;
93 
97  private $filesystem;
98 
102  private $objectManager;
103 
107  private $configModel;
108 
112  private $cleanupFiles;
113 
117  private $dbValidator;
118 
122  private $setupFactory;
123 
127  private $dataSetupFactory;
128 
132  private $sampleDataState;
133 
137  private $componentRegistrar;
138 
142  private $phpReadinessCheck;
143 
147  private $declarationInstallerMock;
148 
152  private $schemaListenerMock;
153 
158  private static $dbConfig = [
159  'default' => [
164  ]
165  ];
166 
170  private $contextMock;
171 
175  private $patchApplierMock;
176 
180  private $patchApplierFactoryMock;
181 
182  protected function setUp()
183  {
184  $this->filePermissions = $this->createMock(\Magento\Framework\Setup\FilePermissions::class);
185  $this->configWriter = $this->createMock(\Magento\Framework\App\DeploymentConfig\Writer::class);
186  $this->configReader = $this->createMock(\Magento\Framework\App\DeploymentConfig\Reader::class);
187  $this->config = $this->createMock(\Magento\Framework\App\DeploymentConfig::class);
188 
189  $this->moduleList = $this->getMockForAbstractClass(\Magento\Framework\Module\ModuleListInterface::class);
190  $this->moduleList->expects($this->any())->method('getOne')->willReturn(
191  ['setup_version' => '2.0.0']
192  );
193  $this->moduleList->expects($this->any())->method('getNames')->willReturn(
194  ['Foo_One', 'Bar_Two']
195  );
196  $this->moduleLoader = $this->createMock(\Magento\Framework\Module\ModuleList\Loader::class);
197  $this->directoryList =
198  $this->createMock(\Magento\Framework\App\Filesystem\DirectoryList::class);
199  $this->adminFactory = $this->createMock(\Magento\Setup\Model\AdminAccountFactory::class);
200  $this->logger = $this->getMockForAbstractClass(\Magento\Framework\Setup\LoggerInterface::class);
201  $this->random = $this->createMock(\Magento\Framework\Math\Random::class);
202  $this->connection = $this->getMockForAbstractClass(\Magento\Framework\DB\Adapter\AdapterInterface::class);
203  $this->maintenanceMode = $this->createMock(\Magento\Framework\App\MaintenanceMode::class);
204  $this->filesystem = $this->createMock(\Magento\Framework\Filesystem::class);
205  $this->objectManager = $this->getMockForAbstractClass(\Magento\Framework\ObjectManagerInterface::class);
206  $this->contextMock =
207  $this->createMock(\Magento\Framework\Model\ResourceModel\Db\Context::class);
208  $this->configModel = $this->createMock(\Magento\Setup\Model\ConfigModel::class);
209  $this->cleanupFiles = $this->createMock(\Magento\Framework\App\State\CleanupFiles::class);
210  $this->dbValidator = $this->createMock(\Magento\Setup\Validator\DbValidator::class);
211  $this->setupFactory = $this->createMock(\Magento\Setup\Module\SetupFactory::class);
212  $this->dataSetupFactory = $this->createMock(\Magento\Setup\Module\DataSetupFactory::class);
213  $this->sampleDataState = $this->createMock(\Magento\Framework\Setup\SampleData\State::class);
214  $this->componentRegistrar =
215  $this->createMock(\Magento\Framework\Component\ComponentRegistrar::class);
216  $this->phpReadinessCheck = $this->createMock(\Magento\Setup\Model\PhpReadinessCheck::class);
217  $this->declarationInstallerMock = $this->createMock(DeclarationInstaller::class);
218  $this->schemaListenerMock = $this->createMock(SchemaListener::class);
219  $this->patchApplierFactoryMock = $this->createMock(PatchApplierFactory::class);
220  $this->patchApplierMock = $this->createMock(PatchApplier::class);
221  $this->patchApplierFactoryMock->expects($this->any())->method('create')->willReturn(
222  $this->patchApplierMock
223  );
224  $this->object = $this->createObject();
225  }
226 
233  private function createObject($connectionFactory = false, $objectManagerProvider = false)
234  {
235  if (!$connectionFactory) {
236  $connectionFactory = $this->createMock(\Magento\Setup\Module\ConnectionFactory::class);
237  $connectionFactory->expects($this->any())->method('create')->willReturn($this->connection);
238  }
239  if (!$objectManagerProvider) {
240  $objectManagerProvider =
241  $this->createMock(\Magento\Setup\Model\ObjectManagerProvider::class);
242  $objectManagerProvider->expects($this->any())->method('get')->willReturn($this->objectManager);
243  }
244 
245  return new Installer(
246  $this->filePermissions,
247  $this->configWriter,
248  $this->configReader,
249  $this->config,
250  $this->moduleList,
251  $this->moduleLoader,
252  $this->adminFactory,
253  $this->logger,
254  $connectionFactory,
255  $this->maintenanceMode,
256  $this->filesystem,
257  $objectManagerProvider,
258  $this->contextMock,
259  $this->configModel,
260  $this->cleanupFiles,
261  $this->dbValidator,
262  $this->setupFactory,
263  $this->dataSetupFactory,
264  $this->sampleDataState,
265  $this->componentRegistrar,
266  $this->phpReadinessCheck,
267  $this->declarationInstallerMock
268  );
269  }
270 
277  public function testInstall(array $request, array $logMessages)
278  {
279  $this->config->expects($this->atLeastOnce())
280  ->method('get')
281  ->willReturnMap(
282  [
285  ['modules/Magento_User', null, '1']
286  ]
287  );
288  $allModules = ['Foo_One' => [], 'Bar_Two' => []];
289 
290  $this->declarationInstallerMock->expects($this->once())->method('installSchema');
291  $this->moduleLoader->expects($this->any())->method('load')->willReturn($allModules);
292  $setup = $this->createMock(\Magento\Setup\Module\Setup::class);
293  $table = $this->createMock(\Magento\Framework\DB\Ddl\Table::class);
294  $connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)
295  ->setMethods(['getSchemaListener', 'newTable'])
296  ->getMockForAbstractClass();
297  $connection->expects($this->any())->method('getSchemaListener')->willReturn($this->schemaListenerMock);
298  $setup->expects($this->any())->method('getConnection')->willReturn($connection);
299  $table->expects($this->any())->method('addColumn')->willReturn($table);
300  $table->expects($this->any())->method('setComment')->willReturn($table);
301  $table->expects($this->any())->method('addIndex')->willReturn($table);
302  $connection->expects($this->any())->method('newTable')->willReturn($table);
303  $resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
304  $this->contextMock->expects($this->any())->method('getResources')->willReturn($resource);
305  $resource->expects($this->any())->method('getConnection')->will($this->returnValue($connection));
306  $dataSetup = $this->createMock(\Magento\Setup\Module\DataSetup::class);
307  $dataSetup->expects($this->any())->method('getConnection')->willReturn($connection);
308  $cacheManager = $this->createMock(\Magento\Framework\App\Cache\Manager::class);
309  $cacheManager->expects($this->any())->method('getAvailableTypes')->willReturn(['foo', 'bar']);
310  $cacheManager->expects($this->once())->method('setEnabled')->willReturn(['foo', 'bar']);
311  $cacheManager->expects($this->any())->method('clean');
312  $appState = $this->getMockBuilder(\Magento\Framework\App\State::class)
313  ->disableOriginalConstructor()
314  ->disableArgumentCloning()
315  ->getMock();
316  $appState->expects($this->once())
317  ->method('setAreaCode')
318  ->with(\Magento\Framework\App\Area::AREA_GLOBAL);
319  $registry = $this->createMock(\Magento\Framework\Registry::class);
320  $this->setupFactory->expects($this->atLeastOnce())->method('create')->with($resource)->willReturn($setup);
321  $this->dataSetupFactory->expects($this->atLeastOnce())->method('create')->willReturn($dataSetup);
322  $this->objectManager->expects($this->any())
323  ->method('create')
324  ->will($this->returnValueMap([
325  [\Magento\Framework\App\Cache\Manager::class, [], $cacheManager],
326  [\Magento\Framework\App\State::class, [], $appState],
327  [
328  PatchApplierFactory::class,
329  ['objectManager' => $this->objectManager],
330  $this->patchApplierFactoryMock
331  ],
332  ]));
333  $this->patchApplierMock->expects($this->exactly(2))->method('applySchemaPatch')->willReturnMap(
334  [
335  ['Bar_Two'],
336  ['Foo_One'],
337  ]
338  );
339  $this->patchApplierMock->expects($this->exactly(2))->method('applyDataPatch')->willReturnMap(
340  [
341  ['Bar_Two'],
342  ['Foo_One'],
343  ]
344  );
345  $this->objectManager->expects($this->any())
346  ->method('get')
347  ->will($this->returnValueMap([
348  [\Magento\Framework\App\State::class, $appState],
349  [\Magento\Framework\App\Cache\Manager::class, $cacheManager],
350  [\Magento\Setup\Model\DeclarationInstaller::class, $this->declarationInstallerMock],
351  [\Magento\Framework\Registry::class, $registry]
352  ]));
353  $this->adminFactory->expects($this->any())->method('create')->willReturn(
354  $this->createMock(\Magento\Setup\Model\AdminAccount::class)
355  );
356  $this->sampleDataState->expects($this->once())->method('hasError')->willReturn(true);
357  $this->phpReadinessCheck->expects($this->once())->method('checkPhpExtensions')->willReturn(
358  ['responseType' => \Magento\Setup\Controller\ResponseTypeInterface::RESPONSE_TYPE_SUCCESS]
359  );
360  $this->filePermissions->expects($this->any())
361  ->method('getMissingWritablePathsForInstallation')
362  ->willReturn([]);
363  $this->filePermissions->expects($this->once())
364  ->method('getMissingWritableDirectoriesForDbUpgrade')
365  ->willReturn([]);
366  call_user_func_array(
367  [
368  $this->logger->expects($this->exactly(count($logMessages)))->method('log'),
369  'withConsecutive'
370  ],
371  $logMessages
372  );
373  $this->logger->expects($this->exactly(2))
374  ->method('logSuccess')
375  ->withConsecutive(
376  ['Magento installation complete.'],
377  ['Magento Admin URI: /']
378  );
379 
380  $this->object->install($request);
381  }
382 
386  public function installDataProvider()
387  {
388  return [
389  [
390  'request' => [
395  ConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME => 'backend',
396  ],
397  'logMessages' => [
398  ['Starting Magento installation:'],
399  ['File permissions check...'],
400  ['Required extensions check...'],
401  ['Enabling Maintenance Mode...'],
402  ['Installing deployment configuration...'],
403  ['Installing database schema:'],
404  ['Schema creation/updates:'],
405  ['Module \'Foo_One\':'],
406  ['Module \'Bar_Two\':'],
407  ['Schema post-updates:'],
408  ['Module \'Foo_One\':'],
409  ['Module \'Bar_Two\':'],
410  ['Installing user configuration...'],
411  ['Enabling caches:'],
412  ['Current status:'],
413  [''],
414  ['Installing data...'],
415  ['Data install/update:'],
416  ['Module \'Foo_One\':'],
417  ['Module \'Bar_Two\':'],
418  ['Data post-updates:'],
419  ['Module \'Foo_One\':'],
420  ['Module \'Bar_Two\':'],
421  //['Installing admin user...'],
422  ['Caches clearing:'],
423  ['Cache cleared successfully'],
424  ['Disabling Maintenance Mode:'],
425  ['Post installation file permissions check...'],
426  ['Write installation date...'],
427  ['Sample Data is installed with errors. See log file for details']
428  ],
429  ],
430  [
431  'request' => [
436  ConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME => 'backend',
437  AdminAccount::KEY_USER => 'admin',
442  ],
443  'logMessages' => [
444  ['Starting Magento installation:'],
445  ['File permissions check...'],
446  ['Required extensions check...'],
447  ['Enabling Maintenance Mode...'],
448  ['Installing deployment configuration...'],
449  ['Installing database schema:'],
450  ['Schema creation/updates:'],
451  ['Module \'Foo_One\':'],
452  ['Module \'Bar_Two\':'],
453  ['Schema post-updates:'],
454  ['Module \'Foo_One\':'],
455  ['Module \'Bar_Two\':'],
456  ['Installing user configuration...'],
457  ['Enabling caches:'],
458  ['Current status:'],
459  [''],
460  ['Installing data...'],
461  ['Data install/update:'],
462  ['Module \'Foo_One\':'],
463  ['Module \'Bar_Two\':'],
464  ['Data post-updates:'],
465  ['Module \'Foo_One\':'],
466  ['Module \'Bar_Two\':'],
467  ['Installing admin user...'],
468  ['Caches clearing:'],
469  ['Cache cleared successfully'],
470  ['Disabling Maintenance Mode:'],
471  ['Post installation file permissions check...'],
472  ['Write installation date...'],
473  ['Sample Data is installed with errors. See log file for details']
474  ],
475  ],
476  ];
477  }
478 
480  {
481  $this->filePermissions
482  ->expects($this->once())
483  ->method('getMissingWritablePathsForInstallation')
484  ->willReturn([]);
485  $this->object->checkInstallationFilePermissions();
486  }
487 
493  {
494  $this->filePermissions
495  ->expects($this->once())
496  ->method('getMissingWritablePathsForInstallation')
497  ->willReturn(['foo', 'bar']);
498  $this->object->checkInstallationFilePermissions();
499  }
500 
501  public function testCheckExtensions()
502  {
503  $this->phpReadinessCheck->expects($this->once())->method('checkPhpExtensions')->willReturn(
504  ['responseType' => \Magento\Setup\Controller\ResponseTypeInterface::RESPONSE_TYPE_SUCCESS]
505  );
506  $this->object->checkExtensions();
507  }
508 
513  public function testCheckExtensionsError()
514  {
515  $this->phpReadinessCheck->expects($this->once())->method('checkPhpExtensions')->willReturn(
516  [
517  'responseType' => \Magento\Setup\Controller\ResponseTypeInterface::RESPONSE_TYPE_ERROR,
518  'data' => ['required' => ['foo', 'bar'], 'missing' => ['foo']]
519  ]
520  );
521  $this->object->checkExtensions();
522  }
523 
525  {
526  $this->filePermissions
527  ->expects($this->once())
528  ->method('getUnnecessaryWritableDirectoriesForApplication')
529  ->willReturn(['foo', 'bar']);
530  $expectedMessage = "For security, remove write permissions from these directories: 'foo' 'bar'";
531  $this->logger->expects($this->once())->method('log')->with($expectedMessage);
532  $this->object->checkApplicationFilePermissions();
533  $this->assertSame(['message' => [$expectedMessage]], $this->object->getInstallInfo());
534  }
535 
536  public function testUpdateModulesSequence()
537  {
538  $this->cleanupFiles->expects($this->once())->method('clearCodeGeneratedFiles')->will(
539  $this->returnValue(
540  [
541  "The directory '/generation' doesn't exist - skipping cleanup",
542  ]
543  )
544  );
545  $installer = $this->prepareForUpdateModulesTests();
546 
547  $this->logger->expects($this->at(0))->method('log')->with('Cache cleared successfully');
548  $this->logger->expects($this->at(1))->method('log')->with('File system cleanup:');
549  $this->logger->expects($this->at(2))->method('log')
550  ->with('The directory \'/generation\' doesn\'t exist - skipping cleanup');
551  $this->logger->expects($this->at(3))->method('log')->with('Updating modules:');
552  $installer->updateModulesSequence(false);
553  }
554 
556  {
557  $this->cleanupFiles->expects($this->never())->method('clearCodeGeneratedClasses');
558 
559  $installer = $this->prepareForUpdateModulesTests();
560 
561  $this->logger->expects($this->at(0))->method('log')->with('Cache cleared successfully');
562  $this->logger->expects($this->at(1))->method('log')->with('Updating modules:');
563  $installer->updateModulesSequence(true);
564  }
565 
566  public function testUninstall()
567  {
568  $this->config->expects($this->once())
569  ->method('get')
571  ->willReturn([]);
572  $this->configReader->expects($this->once())->method('getFiles')->willReturn([
573  'ConfigOne.php',
574  'ConfigTwo.php'
575  ]);
576  $configDir = $this->getMockForAbstractClass(
577  \Magento\Framework\Filesystem\Directory\WriteInterface::class
578  );
579  $configDir
580  ->expects($this->exactly(2))
581  ->method('getAbsolutePath')
582  ->will(
583  $this->returnValueMap(
584  [
585  ['ConfigOne.php', '/config/ConfigOne.php'],
586  ['ConfigTwo.php', '/config/ConfigTwo.php']
587  ]
588  )
589  );
590  $this->filesystem
591  ->expects($this->any())
592  ->method('getDirectoryWrite')
593  ->will($this->returnValueMap([
595  ]));
596  $this->logger->expects($this->at(0))->method('log')->with('Starting Magento uninstallation:');
597  $this->logger
598  ->expects($this->at(2))
599  ->method('log')
600  ->with('No database connection defined - skipping database cleanup');
601  $cacheManager = $this->createMock(\Magento\Framework\App\Cache\Manager::class);
602  $cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['foo', 'bar']);
603  $cacheManager->expects($this->once())->method('clean');
604  $this->objectManager->expects($this->any())
605  ->method('get')
606  ->with(\Magento\Framework\App\Cache\Manager::class)
607  ->willReturn($cacheManager);
608  $this->logger->expects($this->at(1))->method('log')->with('Cache cleared successfully');
609  $this->logger->expects($this->at(3))->method('log')->with('File system cleanup:');
610  $this->logger
611  ->expects($this->at(4))
612  ->method('log')
613  ->with("The directory '/var' doesn't exist - skipping cleanup");
614  $this->logger
615  ->expects($this->at(5))
616  ->method('log')
617  ->with("The directory '/static' doesn't exist - skipping cleanup");
618  $this->logger
619  ->expects($this->at(6))
620  ->method('log')
621  ->with("The file '/config/ConfigOne.php' doesn't exist - skipping cleanup");
622  $this->logger
623  ->expects($this->at(7))
624  ->method('log')
625  ->with("The file '/config/ConfigTwo.php' doesn't exist - skipping cleanup");
626  $this->logger->expects($this->once())->method('logSuccess')->with('Magento uninstallation complete.');
627  $this->cleanupFiles->expects($this->once())->method('clearAllFiles')->will(
628  $this->returnValue(
629  [
630  "The directory '/var' doesn't exist - skipping cleanup",
631  "The directory '/static' doesn't exist - skipping cleanup"
632  ]
633  )
634  );
635 
636  $this->object->uninstall();
637  }
638 
639  public function testCleanupDb()
640  {
641  $this->config->expects($this->once())
642  ->method('get')
644  ->willReturn(self::$dbConfig);
645  $this->connection->expects($this->at(0))->method('quoteIdentifier')->with('magento')->willReturn(
646  '`magento`'
647  );
648  $this->connection->expects($this->at(1))->method('query')->with('DROP DATABASE IF EXISTS `magento`');
649  $this->connection->expects($this->at(2))->method('query')->with('CREATE DATABASE IF NOT EXISTS `magento`');
650  $this->logger->expects($this->once())->method('log')->with('Cleaning up database `magento`');
651  $this->object->cleanupDb();
652  }
653 
658  private function prepareForUpdateModulesTests()
659  {
660  $allModules = [
661  'Foo_One' => [],
662  'Bar_Two' => [],
663  'New_Module' => [],
664  ];
665 
666  $cacheManager = $this->createMock(\Magento\Framework\App\Cache\Manager::class);
667  $cacheManager->expects($this->once())->method('getAvailableTypes')->willReturn(['foo', 'bar']);
668  $cacheManager->expects($this->once())->method('clean');
669  $this->objectManager->expects($this->any())
670  ->method('get')
671  ->will($this->returnValueMap([
672  [\Magento\Framework\App\Cache\Manager::class, $cacheManager]
673  ]));
674  $this->moduleLoader->expects($this->once())->method('load')->willReturn($allModules);
675 
676  $expectedModules = [
678  'modules' => [
679  'Bar_Two' => 0,
680  'Foo_One' => 1,
681  'New_Module' => 1
682  ]
683  ]
684  ];
685 
686  $this->config->expects($this->atLeastOnce())
687  ->method('get')
689  ->willReturn(true);
690 
691  $newObject = $this->createObject(false, false);
692  $this->configReader->expects($this->once())->method('load')
693  ->willReturn(['modules' => ['Bar_Two' => 0, 'Foo_One' => 1, 'Old_Module' => 0]]);
694  $this->configWriter->expects($this->once())->method('saveConfig')->with($expectedModules);
695 
696  return $newObject;
697  }
698  }
699 }
700 
702 
709  {
710  return ['mock_function_one', 'mock_function_two'];
711  }
712 }
testInstall(array $request, array $logMessages)
$resource
Definition: bulk.php:12
$setup
Definition: trigger.php:12
$table
Definition: trigger.php:14