diff --git a/app/code/Magento/AmqpStore/Plugin/Framework/Amqp/Bulk/Exchange.php b/app/code/Magento/AmqpStore/Plugin/Framework/Amqp/Bulk/Exchange.php index 37960a64d3861..a09fc9d02063c 100644 --- a/app/code/Magento/AmqpStore/Plugin/Framework/Amqp/Bulk/Exchange.php +++ b/app/code/Magento/AmqpStore/Plugin/Framework/Amqp/Bulk/Exchange.php @@ -24,14 +24,14 @@ class Exchange { /** - * @var StoreManagerInterface + * @var EnvelopeFactory */ - private $storeManager; + private $envelopeFactory; /** - * @var EnvelopeFactory + * @var StoreManagerInterface */ - private $envelopeFactory; + private $storeManager; /** * @var LoggerInterface @@ -49,8 +49,8 @@ public function __construct( StoreManagerInterface $storeManager, LoggerInterface $logger ) { - $this->storeManager = $storeManager; $this->envelopeFactory = $envelopeFactory; + $this->storeManager = $storeManager; $this->logger = $logger; } @@ -83,9 +83,6 @@ public function beforeEnqueue(SubjectExchange $subject, $topic, array $envelopes $updatedEnvelopes = []; foreach ($envelopes as $envelope) { $properties = $envelope->getProperties(); - if (!isset($properties)) { - $properties = []; - } if (isset($properties['application_headers'])) { $headers = $properties['application_headers']; if ($headers instanceof AMQPTable) { diff --git a/app/code/Magento/AmqpStore/Test/Unit/Plugin/AsynchronousOperations/MassConsumerEnvelopeCallbackTest.php b/app/code/Magento/AmqpStore/Test/Unit/Plugin/AsynchronousOperations/MassConsumerEnvelopeCallbackTest.php new file mode 100644 index 0000000000000..bdd81a7096bb6 --- /dev/null +++ b/app/code/Magento/AmqpStore/Test/Unit/Plugin/AsynchronousOperations/MassConsumerEnvelopeCallbackTest.php @@ -0,0 +1,200 @@ +subjectMassConsumerEnvelopeCallbackMock = $this->createMock(SubjectMassConsumerEnvelopeCallback::class); + $this->storeMock = $this->createMock(Store::class); + $this->messageMock = $this->getMockForAbstractClass(EnvelopeInterface::class); + + $this->envelopeFactoryMock = $this->createMock(EnvelopeFactory::class); + $this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class); + $this->loggerMock = $this->getMockForAbstractClass(\Psr\Log\LoggerInterface::class); + + $objectManager = new ObjectManager($this); + $this->massConsumerEnvelopeCallbackPlugin = $objectManager->getObject( + MassConsumerEnvelopeCallback::class, + [ + 'envelopeFactory' => $this->envelopeFactoryMock, + 'storeManager' => $this->storeManagerMock, + 'logger' => $this->loggerMock, + ] + ); + } + + public function testAroundExecuteWhenApplicationHeadersDoesNotExist() + { + $this->messageMock->expects($this->once()) + ->method('getProperties') + ->willReturn(null); + + $isProceedCalled = false; + $proceed = function ($message) use (&$isProceedCalled) { + $isProceedCalled = !!$message; + }; + + $this->massConsumerEnvelopeCallbackPlugin->aroundExecute( + $this->subjectMassConsumerEnvelopeCallbackMock, + $proceed, + $this->messageMock + ); + + $this->assertTrue($isProceedCalled); + } + + public function testAroundExecuteWhenCanNotGetCurrentStoreId() + { + $storeId = 333; + $headers = ['store_id' => $storeId]; + + $amqpProperties = ['application_headers' => $headers]; + $this->messageMock->expects($this->once()) + ->method('getProperties') + ->willReturn($amqpProperties); + + $message = 'no_such_entity_exception'; + $this->storeManagerMock + ->expects($this->once()) + ->method('getStore') + ->willThrowException(new NoSuchEntityException(__($message))); + + $this->loggerMock + ->expects($this->once()) + ->method('error') + ->with("Can't set currentStoreId during processing queue. Message rejected. Error $message."); + + $queue = $this->getMockBuilder(QueueInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->subjectMassConsumerEnvelopeCallbackMock + ->expects($this->once()) + ->method('getQueue') + ->willReturn($queue); + $queue + ->expects($this->once()) + ->method('reject') + ->with($this->messageMock, false, $message); + + $isProceedCalled = false; + $proceed = function ($message) use (&$isProceedCalled) { + $isProceedCalled = !!$message; + }; + + $this->massConsumerEnvelopeCallbackPlugin->aroundExecute( + $this->subjectMassConsumerEnvelopeCallbackMock, + $proceed, + $this->messageMock + ); + + $this->assertFalse($isProceedCalled); + } + + /** + * @dataProvider provideApplicationHeadersForAroundExecuteSuccess + * + * @param array|AMQPTable $headers + * @param int $storeId + * @param int $currentStoreId + */ + public function testAroundExecuteWhenSuccess($headers, int $storeId, int $currentStoreId) + { + $amqpProperties = ['application_headers' => $headers]; + $this->messageMock->expects($this->once()) + ->method('getProperties') + ->willReturn($amqpProperties); + + $this->storeManagerMock->expects($this->once()) + ->method('getStore') + ->willReturn($this->storeMock); + $this->storeMock->expects($this->once()) + ->method('getId') + ->willReturn($currentStoreId); + + $this->storeManagerMock->expects($this->exactly(2)) + ->method('setCurrentStore') + ->withConsecutive( + [$storeId], + [$currentStoreId] + ); + + $isProceedCalled = false; + $proceed = function ($message) use (&$isProceedCalled) { + $isProceedCalled = !!$message; + }; + + $this->massConsumerEnvelopeCallbackPlugin->aroundExecute( + $this->subjectMassConsumerEnvelopeCallbackMock, + $proceed, + $this->messageMock + ); + + $this->assertTrue($isProceedCalled); + } + + public function provideApplicationHeadersForAroundExecuteSuccess() + { + $storeId = 123; + $currentStoreId = 99; + + return [ + [['store_id' => 123], $storeId, $currentStoreId], + [new AMQPTable(['store_id' => 123]), $storeId, $currentStoreId], + ]; + } +} diff --git a/app/code/Magento/AmqpStore/Test/Unit/Plugin/Framework/Amqp/Bulk/ExchangeTest.php b/app/code/Magento/AmqpStore/Test/Unit/Plugin/Framework/Amqp/Bulk/ExchangeTest.php new file mode 100644 index 0000000000000..96fc9572bb7d3 --- /dev/null +++ b/app/code/Magento/AmqpStore/Test/Unit/Plugin/Framework/Amqp/Bulk/ExchangeTest.php @@ -0,0 +1,236 @@ +subjectExchange = $this->createMock(SubjectExchange::class); + $this->storeMock = $this->createMock(Store::class); + + $this->envelopeFactoryMock = $this->createMock(EnvelopeFactory::class); + $this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class); + $this->loggerMock = $this->getMockForAbstractClass(\Psr\Log\LoggerInterface::class); + + $objectManager = new ObjectManager($this); + $this->exchangePlugin = $objectManager->getObject( + Exchange::class, + [ + 'envelopeFactory' => $this->envelopeFactoryMock, + 'storeManager' => $this->storeManagerMock, + 'logger' => $this->loggerMock, + ] + ); + } + + public function testBeforeEnqueueWhenCanNotGetCurrentStoreId() + { + $topic = 'test_topic'; + $envelopes = []; + + $message = 'no_such_entity_exception'; + $this->storeManagerMock + ->expects($this->once()) + ->method('getStore') + ->willThrowException(new NoSuchEntityException(__($message))); + $this->loggerMock + ->expects($this->once()) + ->method('error') + ->with("Can't get current storeId and inject to amqp message. Error $message."); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage("Can't get current storeId and inject to amqp message. Error $message."); + + $this->exchangePlugin->beforeEnqueue( + $this->subjectExchange, + $topic, + $envelopes + ); + } + + public function testBeforeEnqueueWhenEnvelopePropertiesNull() + { + $topic = 'test_topic'; + $envelope_1 = $this->getMockForAbstractClass(EnvelopeInterface::class); + $envelopes = [$envelope_1]; + $storeId = 123; + + $this->prepareMocksToGetStoreId($storeId); + + $envelope_1 + ->expects($this->once()) + ->method('getProperties'); + + $body = 'envelope_body'; + $envelope_1 + ->expects($this->once()) + ->method('getBody') + ->willReturn($body); + + $newEnvelope = $this->getMockForAbstractClass(EnvelopeInterface::class); + $this->envelopeFactoryMock + ->expects($this->once()) + ->method('create') + ->with( + [ + 'body' => $body, + 'properties' => ['application_headers' => new AMQPTable(['store_id' => $storeId])] + ] + )->willReturn($newEnvelope); + + $actualResult = $this->exchangePlugin->beforeEnqueue( + $this->subjectExchange, + $topic, + $envelopes + ); + + $this->assertSame($topic, $actualResult[0]); + $this->assertSame($newEnvelope, $actualResult[1][0]); + } + + public function testBeforeEnqueueWhenHeaderIsAmqpTableButCanNotSetStoreId() + { + $topic = 'test_topic_xxx'; + $envelope_1 = $this->getMockForAbstractClass(EnvelopeInterface::class); + $envelopes = [$envelope_1]; + $storeId = 123; + $headers = $this->createMock(AMQPTable::class); + $properties = ['application_headers' => $headers]; + + $this->prepareMocksToGetStoreId($storeId); + + $envelope_1 + ->expects($this->once()) + ->method('getProperties') + ->willReturn($properties); + + $exceptionMessage = 'errrorrrr!'; + $headers + ->expects($this->once()) + ->method('set') + ->with('store_id', $storeId) + ->willThrowException(new AMQPInvalidArgumentException($exceptionMessage)); + $this->loggerMock + ->expects($this->once()) + ->method('error') + ->with("Can't set storeId to amqp message. Error $exceptionMessage."); + + $this->expectException(AMQPInvalidArgumentException::class); + $this->expectExceptionMessage("Can't set storeId to amqp message. Error $exceptionMessage."); + + $this->exchangePlugin->beforeEnqueue( + $this->subjectExchange, + $topic, + $envelopes + ); + } + + public function testBeforeEnqueueWhenIsAmqpTableAndSuccess() + { + $topic = 'test_topic'; + $envelope_1 = $this->getMockForAbstractClass(EnvelopeInterface::class); + $envelopes = [$envelope_1]; + $storeId = 999; + $headers = $this->createMock(AMQPTable::class); + $properties = ['application_headers' => $headers]; + + $this->prepareMocksToGetStoreId($storeId); + + $envelope_1 + ->expects($this->once()) + ->method('getProperties') + ->willReturn($properties); + $headers + ->expects($this->once()) + ->method('set') + ->with('store_id', $storeId); + + $body = 'envelope_body'; + $envelope_1 + ->expects($this->once()) + ->method('getBody') + ->willReturn($body); + + $newEnvelope = $this->getMockForAbstractClass(EnvelopeInterface::class); + $this->envelopeFactoryMock + ->expects($this->once()) + ->method('create') + ->with( + [ + 'body' => $body, + 'properties' => ['application_headers' => $headers] + ] + )->willReturn($newEnvelope); + + $actualResult = $this->exchangePlugin->beforeEnqueue( + $this->subjectExchange, + $topic, + $envelopes + ); + + $this->assertSame($topic, $actualResult[0]); + $this->assertSame($newEnvelope, $actualResult[1][0]); + $this->assertSame(1, count($actualResult[1])); + } + + private function prepareMocksToGetStoreId(int $storeId) + { + $this->storeManagerMock + ->expects($this->once()) + ->method('getStore') + ->willReturn($this->storeMock); + $this->storeMock + ->expects($this->once()) + ->method('getId') + ->willReturn($storeId); + } +}