У меня есть определённая логика, которую необходимо покрыть тестами, а именно
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 вызывается в том случае, когда буфер полностью заполнен.
Я покрыла данную логику следующим, тестом, а именно для проверки удаления
/**
* @test
* @throws Exception
*/
public function deleteHandleTest(): void
{
/** @var ConsumerMessage|MockInterface $message */
$message = Mockery::mock(ConsumerMessage::class);
$message->shouldReceive('getAction')->once()->with()->andReturn('delete');
$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']);
$this->handler = new EventSystemHandler(
$this->converter,
$this->eventManager,
$this->tm,
$this->insertOnDuplicateKeyUpdateTransactionFactory,
$this->allowedFcMpnIdsFilter,
self::MAX_BUFFER_SIZE
);
$result = $this->handler->handle($message);
self::assertTrue($result, 'The method handle must return true on successful processing.');
// Проверяем состояние буфера identifiersBufferByAction
$expectedBuffer = [
'delete' => [
'1' => '1',
'2' => '2',
'3' => '3'
],
];
$reflection = new ReflectionClass($this->handler); //add reflection
$property = $reflection->getProperty('identifiersBufferByAction');
$property->setAccessible(true);
$actualBuffer = $property->getValue($this->handler);
self::assertEquals(
$expectedBuffer,
$actualBuffer,
'The identifiersBufferByAction buffer must contain only identifiers that pass the filter'
);
$expectedMarketplaceProductIdToMpnId = [
'1' => '11',
'2' => '22',
'3' => '33'
];
$reflection = new ReflectionClass($this->handler);
$property = $reflection->getProperty('marketplaceProductIdToMpnId');
$property->setAccessible(true);
$actualMarketplaceProductIdToMpnId = $property->getValue($this->handler);
self::assertEquals(
$expectedMarketplaceProductIdToMpnId,
$actualMarketplaceProductIdToMpnId,
'The marketplaceProductIdToMpnId array must contain the mapping of marketplace_product_id to mpn_id'
);
$trData = [
[
ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID => '11',
ProductQueue::TABLE_COLUMN_OPERATION_TYPE => ProductQueue::ENUM_OPERATION_TYPE_DELETE,
ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => '1',
],
[
ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID => '22',
ProductQueue::TABLE_COLUMN_OPERATION_TYPE => ProductQueue::ENUM_OPERATION_TYPE_DELETE,
ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => '2',
],
[
ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID => '33',
ProductQueue::TABLE_COLUMN_OPERATION_TYPE => ProductQueue::ENUM_OPERATION_TYPE_DELETE,
ProductQueue::TABLE_COLUMN_MARKETPLACE_PRODUCT_ID => '3',
]
];
$this->insertOnDuplicateKeyUpdateTransactionFactory->shouldReceive('factory')
->once()
->with(
ProductQueue::class,
$trData,
[ProductQueue::TABLE_COLUMN_MPN_PRODUCT_ID]
)
->andReturn(); //problem
$this->tm->shouldNotHaveReceived('doTransaction')->once();
}
Я не совсем понимаю во-первых, что мне здесь для корректности необходимо вернуть
->andReturn(); //problem
А во-вторых при запуске теста, я вижу следующую ошибку
Mockery\Exception\BadMethodCallException : Received Mockery_3_App_Transactions_Factories_InsertOnDuplicateKeyUpdateTransactionFactory::factory(), but no expectations were specified
Не понимаю уже куда копать и что не так. Прошу помощи