Задать вопрос
@tanuxa2022

Как устранить ошибку «Mockery\Exception\NoMatchingExpectationException»?

У меня есть определённая логика, которую необходимо покрыть тестами, а именно
public function handle(ConsumerMessage $message): bool
    {
        $action = $message->getAction();

        $mpnIdBrandIdSkuMarketplaceIds = $this->converter->convert($message);

        if (empty($mpnIdBrandIdSkuMarketplaceIds) === false) {
            $mpnIds = ArrayHelper::arrayColumnUnique($mpnIdBrandIdSkuMarketplaceIds, self::MPN_ID_FIELD);

            $this->eventManager->triggerEvent(new NewEventSystemMessageEvent($message, $mpnIds));

            $allowedMpnIds                = $this->allowedFcMpnIdsFilter->filter($mpnIds);
            $allowedMpnIdsIndexedByMpnIds = array_combine($allowedMpnIds, $allowedMpnIds);

            foreach ($mpnIdBrandIdSkuMarketplaceIds as $item) {
                $mpnId         = $item[self::MPN_ID_FIELD];
                $marketplaceId = $item[self::MARKETPLACE_PRODUCT_ID_FIELD];

                if (self::DELETE_ACTION === $action) {
                    if ($marketplaceId !== null) {
                        $this->identifiersBufferByAction[$action][$marketplaceId] = $marketplaceId;
                        $this->marketplaceProductIdToMpnId[$marketplaceId] = $mpnId;
                    }
                } elseif (isset($allowedMpnIdsIndexedByMpnIds[$mpnId])) {
                    $this->identifiersBufferByAction[$action][$mpnId] = $mpnId;
                }
            }
        }

        foreach ($this->identifiersBufferByAction as $action => $identifiers) {
            if ($this->maxBufferSize <= count($identifiers)) {
                $this->innerFlush($action, $identifiers);
            }
        }

        return true;
    }

    /**
     * @throws InvalidArgumentException
     * @throws Exception
     */
    private function innerFlush(string $action, array $identifiers): void
    {
        $ids = array_keys($identifiers);
        if (count($ids) > 0) {
            $isDeleteAction = self::DELETE_ACTION === $action;

            $trData = [];

            if (!$isDeleteAction) {
                foreach ($ids as $mpnProductId) {
                    $trData[] = [
                        ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID         => $mpnProductId,
                        ProductQueue::TABLE_COLUMN_OPERATION_TYPE         => ProductQueue::ENUM_OPERATION_TYPE_UPDATE,
                        ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => null
                    ];
                }

                $transaction = $this->insertOnDuplicateKeyUpdateTransactionFactory->factory(
                    ProductQueue::class,
                    $trData,
                    [
                        ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID
                    ]
                );
            } else {
                foreach ($ids as $marketplaceProductId) {
                    $mpnProductId = $this->marketplaceProductIdToMpnId[$marketplaceProductId] ?? null;
                    if ($mpnProductId !== null) {
                        $trData[] = [
                            ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID         => $mpnProductId,
                            ProductQueue::TABLE_COLUMN_OPERATION_TYPE         => ProductQueue::ENUM_OPERATION_TYPE_DELETE,
                            ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => $marketplaceProductId
                        ];
                    }
                }

                $transaction = $this->insertOnDuplicateKeyUpdateTransactionFactory->factory(
                    ProductQueue::class,
                    $trData,
                    [
                        ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID
                    ]
                );

                $this->marketplaceProductIdToMpnId = [];
            }

            $this->tm->doTransaction($transaction);
        }

        $this->identifiersBufferByAction[$action] = [];
    }


Можно заметить, что метод innerFlush вызывается в том случае, когда буфер полностью заполнен.
Я покрыла данную логику следующим, тестом, а именно для проверки update
/**
     * @test
     * @throws Exception
     */
    public function updateHandleWithBufferOverflowTest(): void {
        /** @var ConsumerMessage|MockInterface $message */
        $message = Mockery::mock(ConsumerMessage::class);
        $message->shouldReceive('getAction')->once()->with()->andReturn('update');

        $converted = [
            [
                'mpn_id'                 => '11',
                'carid_brand_id'         => '111',
                'sku'                    => 'sku1',
                'marketplace_product_id' => '1',
            ],
            [
                'mpn_id'                 => '22',
                'carid_brand_id'         => '222',
                'sku'                    => 'sku2',
                'marketplace_product_id' => '2',
            ],
            [
                'mpn_id'                 => '33',
                'carid_brand_id'         => '333',
                'sku'                    => 'sku3',
                'marketplace_product_id' => '3',
            ],
            [
                'mpn_id'                 => '44',
                'carid_brand_id'         => '444',
                'sku'                    => 'sku4',
                'marketplace_product_id' => '4',
            ],
        ];

        $this->converter->shouldReceive('convert')
            ->once()
            ->with($message)
            ->andReturn($converted);

        $expectedEvent = new NewEventSystemMessageEvent($message);

        $this->eventManager->shouldReceive('triggerEvent')
            ->once()
            ->with(
                Mockery::on(
                    static function (NewEventSystemMessageEvent $actualEvent) use ($expectedEvent) {
                        return $expectedEvent->getMessage() === $actualEvent->getMessage();
                    }
                )
            );

        $this->allowedFcMpnIdsFilter->shouldReceive('filter')
            ->once()
            ->with(['11', '22', '33', '44'])
            ->andReturn(['11', '22', '33', '44']);

        $trData = [
            [
                ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID         => '11',
                ProductQueue::TABLE_COLUMN_OPERATION_TYPE         => ProductQueue::ENUM_OPERATION_TYPE_UPDATE,
                ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => null,
            ],
            [
                ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID         => '22',
                ProductQueue::TABLE_COLUMN_OPERATION_TYPE         => ProductQueue::ENUM_OPERATION_TYPE_UPDATE,
                ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => null,
            ],
            [
                ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID         => '33',
                ProductQueue::TABLE_COLUMN_OPERATION_TYPE         => ProductQueue::ENUM_OPERATION_TYPE_UPDATE,
                ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => null,
            ],
        ];

        $transaction = Mockery::mock(InsertOnDuplicateKeyUpdateTransaction::class);

        $this->insertOnDuplicateKeyUpdateTransactionFactory->shouldReceive('factory')
            ->once()
            ->withArgs(
                [
                    ProductQueue::class,
                    $trData,
                    [
                        ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID
                    ]
                ]
            )
            ->andReturn($transaction);

        $this->tm->shouldReceive('doTransaction')
            ->once()
            ->with($transaction);

        $this->handler = new EventSystemHandler(
            $this->converter,
            $this->eventManager,
            $this->tm,
            $this->insertOnDuplicateKeyUpdateTransactionFactory,
            $this->allowedFcMpnIdsFilter,
            self::MAX_BUFFER_SIZE
        );

        $reflection = new ReflectionClass($this->handler);
        $property = $reflection->getProperty('identifiersBufferByAction');
        $property->setAccessible(true);

        $bufferBefore = $property->getValue($this->handler);
        self::assertEmpty($bufferBefore, 'Buffer must be empty before handle is called.');

        $this->handler->handle($message);

        $bufferAfterHandle = $property->getValue($this->handler);
        var_dump('Buffer after handle:', $bufferAfterHandle);

        $actualBuffer = $property->getValue($this->handler);
        var_dump($actualBuffer);

        $expectedBuffer = [
            'update' => [
                '44' => '44',
            ],
        ];

        self::assertEquals(
            $expectedBuffer,
            $actualBuffer,
            'The identifiersBufferByAction buffer must contain only identifiers that pass the filter'
        );

        $this->tm->shouldHaveReceived('doTransaction')->once();
    }


Но я никак не могу выявить конкретно где ошибка и исправить её.
Текст ошибки: "Mockery\Exception\NoMatchingExpectationException : No matching handler found for Mockery_3_App_Transactions_Factories_InsertOnDuplicateKeyUpdateTransactionFactory::factory('Carid\Amazon\Model\Marketplace\Entities\ProductQueue', [0 => [...], 1 => [...], 2 => [...], 3 => [...]], [0 => 'mpn_product_id']). Either the method was unexpected or its arguments matched no expected argument list for this method"

Желтым подсвечивает следующая строка - $this->handler->handle($message);

Как мне это исправить? или же что добавить? Если убрать данную строку, то ожидаемый и актуальный буфер не являются равными.
  • Вопрос задан
  • 41 просмотр
Подписаться 2 Средний Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы