3 namespace Drupal\Tests\migrate\Unit;
5 use Drupal\Component\Utility\Html;
6 use Drupal\migrate\Plugin\MigrateProcessInterface;
7 use Drupal\migrate\Plugin\MigrationInterface;
8 use Drupal\migrate\Plugin\MigrateIdMapInterface;
9 use Drupal\migrate\MigrateException;
10 use Drupal\migrate\Row;
13 * @coversDefaultClass \Drupal\migrate\MigrateExecutable
16 class MigrateExecutableTest extends MigrateTestCase {
19 * The mocked migration entity.
21 * @var \Drupal\migrate\Plugin\MigrationInterface|\PHPUnit_Framework_MockObject_MockObject
26 * The mocked migrate message.
28 * @var \Drupal\migrate\MigrateMessageInterface|\PHPUnit_Framework_MockObject_MockObject
33 * The tested migrate executable.
35 * @var \Drupal\Tests\migrate\Unit\TestMigrateExecutable
37 protected $executable;
40 * The migration's configuration values.
44 protected $migrationConfiguration = [
51 protected function setUp() {
53 $this->migration = $this->getMigration();
54 $this->message = $this->getMock('Drupal\migrate\MigrateMessageInterface');
55 $event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
56 $this->executable = new TestMigrateExecutable($this->migration, $this->message, $event_dispatcher);
57 $this->executable->setStringTranslation($this->getStringTranslationStub());
61 * Tests an import with an incomplete rewinding.
63 public function testImportWithFailingRewind() {
64 $exception_message = $this->getRandomGenerator()->string();
65 $source = $this->getMock('Drupal\migrate\Plugin\MigrateSourceInterface');
66 $source->expects($this->once())
68 ->will($this->throwException(new \Exception($exception_message)));
70 $this->migration->expects($this->any())
71 ->method('getSourcePlugin')
72 ->will($this->returnValue($source));
74 // Ensure that a message with the proper message was added.
75 $this->message->expects($this->once())
77 ->with("Migration failed with source plugin exception: " . Html::escape($exception_message));
79 $result = $this->executable->import();
80 $this->assertEquals(MigrationInterface::RESULT_FAILED, $result);
84 * Tests the import method with a valid row.
86 public function testImportWithValidRow() {
87 $source = $this->getMockSource();
89 $row = $this->getMockBuilder('Drupal\migrate\Row')
90 ->disableOriginalConstructor()
93 $row->expects($this->once())
94 ->method('getSourceIdValues')
95 ->will($this->returnValue(['id' => 'test']));
97 $this->idMap->expects($this->once())
98 ->method('lookupDestinationId')
99 ->with(['id' => 'test'])
100 ->will($this->returnValue(['test']));
102 $source->expects($this->once())
104 ->will($this->returnValue($row));
106 $this->executable->setSource($source);
108 $this->migration->expects($this->once())
109 ->method('getProcessPlugins')
110 ->will($this->returnValue([]));
112 $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
113 $destination->expects($this->once())
115 ->with($row, ['test'])
116 ->will($this->returnValue(['id' => 'test']));
119 ->method('getDestinationPlugin')
120 ->willReturn($destination);
122 $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
126 * Tests the import method with a valid row.
128 public function testImportWithValidRowWithoutDestinationId() {
129 $source = $this->getMockSource();
131 $row = $this->getMockBuilder('Drupal\migrate\Row')
132 ->disableOriginalConstructor()
135 $row->expects($this->once())
136 ->method('getSourceIdValues')
137 ->will($this->returnValue(['id' => 'test']));
139 $this->idMap->expects($this->once())
140 ->method('lookupDestinationId')
141 ->with(['id' => 'test'])
142 ->will($this->returnValue(['test']));
144 $source->expects($this->once())
146 ->will($this->returnValue($row));
148 $this->executable->setSource($source);
150 $this->migration->expects($this->once())
151 ->method('getProcessPlugins')
152 ->will($this->returnValue([]));
154 $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
155 $destination->expects($this->once())
157 ->with($row, ['test'])
158 ->will($this->returnValue(TRUE));
161 ->method('getDestinationPlugin')
162 ->willReturn($destination);
164 $this->idMap->expects($this->never())
165 ->method('saveIdMapping');
167 $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
171 * Tests the import method with a valid row.
173 public function testImportWithValidRowNoDestinationValues() {
174 $source = $this->getMockSource();
176 $row = $this->getMockBuilder('Drupal\migrate\Row')
177 ->disableOriginalConstructor()
180 $row->expects($this->once())
181 ->method('getSourceIdValues')
182 ->will($this->returnValue(['id' => 'test']));
184 $source->expects($this->once())
186 ->will($this->returnValue($row));
188 $this->executable->setSource($source);
190 $this->migration->expects($this->once())
191 ->method('getProcessPlugins')
192 ->will($this->returnValue([]));
194 $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
195 $destination->expects($this->once())
197 ->with($row, ['test'])
198 ->will($this->returnValue([]));
201 ->method('getDestinationPlugin')
202 ->willReturn($destination);
204 $this->idMap->expects($this->once())
205 ->method('saveIdMapping')
206 ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
208 $this->idMap->expects($this->once())
209 ->method('messageCount')
210 ->will($this->returnValue(0));
212 $this->idMap->expects($this->once())
213 ->method('saveMessage');
215 $this->idMap->expects($this->once())
216 ->method('lookupDestinationId')
217 ->with(['id' => 'test'])
218 ->will($this->returnValue(['test']));
220 $this->message->expects($this->once())
222 ->with('New object was not saved, no error provided');
224 $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
228 * Tests the import method with a thrown MigrateException.
230 * The MigrationException in this case is being thrown from the destination.
232 public function testImportWithValidRowWithDestinationMigrateException() {
233 $exception_message = $this->getRandomGenerator()->string();
234 $source = $this->getMockSource();
236 $row = $this->getMockBuilder('Drupal\migrate\Row')
237 ->disableOriginalConstructor()
240 $row->expects($this->once())
241 ->method('getSourceIdValues')
242 ->will($this->returnValue(['id' => 'test']));
244 $source->expects($this->once())
246 ->will($this->returnValue($row));
248 $this->executable->setSource($source);
250 $this->migration->expects($this->once())
251 ->method('getProcessPlugins')
252 ->will($this->returnValue([]));
254 $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
255 $destination->expects($this->once())
257 ->with($row, ['test'])
258 ->will($this->throwException(new MigrateException($exception_message)));
261 ->method('getDestinationPlugin')
262 ->willReturn($destination);
264 $this->idMap->expects($this->once())
265 ->method('saveIdMapping')
266 ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
268 $this->idMap->expects($this->once())
269 ->method('saveMessage');
271 $this->idMap->expects($this->once())
272 ->method('lookupDestinationId')
273 ->with(['id' => 'test'])
274 ->will($this->returnValue(['test']));
276 $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
280 * Tests the import method with a thrown MigrateException.
282 * The MigrationException in this case is being thrown from a process plugin.
284 public function testImportWithValidRowWithProcesMigrateException() {
285 $exception_message = $this->getRandomGenerator()->string();
286 $source = $this->getMockSource();
288 $row = $this->getMockBuilder('Drupal\migrate\Row')
289 ->disableOriginalConstructor()
292 $row->expects($this->once())
293 ->method('getSourceIdValues')
294 ->willReturn(['id' => 'test']);
296 $source->expects($this->once())
300 $this->executable->setSource($source);
302 $this->migration->expects($this->once())
303 ->method('getProcessPlugins')
304 ->willThrowException(new MigrateException($exception_message));
306 $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
307 $destination->expects($this->never())
311 ->method('getDestinationPlugin')
312 ->willReturn($destination);
314 $this->idMap->expects($this->once())
315 ->method('saveIdMapping')
316 ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
318 $this->idMap->expects($this->once())
319 ->method('saveMessage');
321 $this->idMap->expects($this->never())
322 ->method('lookupDestinationId');
324 $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
328 * Tests the import method with a regular Exception being thrown.
330 public function testImportWithValidRowWithException() {
331 $exception_message = $this->getRandomGenerator()->string();
332 $source = $this->getMockSource();
334 $row = $this->getMockBuilder('Drupal\migrate\Row')
335 ->disableOriginalConstructor()
338 $row->expects($this->once())
339 ->method('getSourceIdValues')
340 ->will($this->returnValue(['id' => 'test']));
342 $source->expects($this->once())
344 ->will($this->returnValue($row));
346 $this->executable->setSource($source);
348 $this->migration->expects($this->once())
349 ->method('getProcessPlugins')
350 ->will($this->returnValue([]));
352 $destination = $this->getMock('Drupal\migrate\Plugin\MigrateDestinationInterface');
353 $destination->expects($this->once())
355 ->with($row, ['test'])
356 ->will($this->throwException(new \Exception($exception_message)));
359 ->method('getDestinationPlugin')
360 ->willReturn($destination);
362 $this->idMap->expects($this->once())
363 ->method('saveIdMapping')
364 ->with($row, [], MigrateIdMapInterface::STATUS_FAILED, NULL);
366 $this->idMap->expects($this->once())
367 ->method('saveMessage');
369 $this->idMap->expects($this->once())
370 ->method('lookupDestinationId')
371 ->with(['id' => 'test'])
372 ->will($this->returnValue(['test']));
374 $this->message->expects($this->once())
376 ->with($exception_message);
378 $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
382 * Tests the processRow method.
384 public function testProcessRow() {
386 'test' => 'test destination',
387 'test1' => 'test1 destination'
389 foreach ($expected as $key => $value) {
390 $plugins[$key][0] = $this->getMock('Drupal\migrate\Plugin\MigrateProcessInterface');
391 $plugins[$key][0]->expects($this->once())
392 ->method('getPluginDefinition')
393 ->will($this->returnValue([]));
394 $plugins[$key][0]->expects($this->once())
395 ->method('transform')
396 ->will($this->returnValue($value));
398 $this->migration->expects($this->once())
399 ->method('getProcessPlugins')
401 ->will($this->returnValue($plugins));
403 $this->executable->processRow($row);
404 foreach ($expected as $key => $value) {
405 $this->assertSame($row->getDestinationProperty($key), $value);
407 $this->assertSame(count($row->getDestination()), count($expected));
411 * Tests the processRow method with an empty pipeline.
413 public function testProcessRowEmptyPipeline() {
414 $this->migration->expects($this->once())
415 ->method('getProcessPlugins')
417 ->will($this->returnValue(['test' => []]));
419 $this->executable->processRow($row);
420 $this->assertSame($row->getDestination(), []);
424 * Tests the processRow pipeline exception.
426 public function testProcessRowPipelineException() {
428 $plugin = $this->prophesize(MigrateProcessInterface::class);
429 $plugin->getPluginDefinition()->willReturn(['handle_multiples' => FALSE]);
430 $plugin->transform(NULL, $this->executable, $row, 'destination_id')
431 ->willReturn('transform_return_string');
432 $plugin->multiple()->willReturn(TRUE);
433 $plugin->getPluginId()->willReturn('plugin_id');
434 $plugin = $plugin->reveal();
435 $plugins['destination_id'] = [$plugin, $plugin];
436 $this->migration->method('getProcessPlugins')->willReturn($plugins);
438 $this->setExpectedException(MigrateException::class, 'Pipeline failed at plugin_id plugin for destination destination_id: transform_return_string received instead of an array,');
439 $this->executable->processRow($row);
443 * Tests the processRow method.
445 public function testProcessRowEmptyDestination() {
447 'test' => 'test destination',
448 'test1' => 'test1 destination',
453 foreach ($expected as $key => $value) {
454 $plugin = $this->prophesize(MigrateProcessInterface::class);
455 $plugin->getPluginDefinition()->willReturn([]);
456 $plugin->transform(NULL, $this->executable, $row, $key)->willReturn($value);
457 $plugin->multiple()->willReturn(TRUE);
458 $plugins[$key][0] = $plugin->reveal();
460 $this->migration->method('getProcessPlugins')->willReturn($plugins);
461 $this->executable->processRow($row);
462 foreach ($expected as $key => $value) {
463 $this->assertSame($value, $row->getDestinationProperty($key));
465 $this->assertCount(2, $row->getDestination());
466 $this->assertSame(['test2'], $row->getEmptyDestinationProperties());
470 * Returns a mock migration source instance.
472 * @return \Drupal\migrate\Plugin\MigrateSourceInterface|\PHPUnit_Framework_MockObject_MockObject
473 * The mocked migration source.
475 protected function getMockSource() {
476 $iterator = $this->getMock('\Iterator');
478 $class = 'Drupal\migrate\Plugin\migrate\source\SourcePluginBase';
479 $source = $this->getMockBuilder($class)
480 ->disableOriginalConstructor()
481 ->setMethods(get_class_methods($class))
482 ->getMockForAbstractClass();
483 $source->expects($this->once())
485 ->will($this->returnValue(TRUE));
486 $source->expects($this->any())
487 ->method('initializeIterator')
488 ->will($this->returnValue([]));
489 $source->expects($this->any())
491 ->will($this->onConsecutiveCalls(TRUE, FALSE));