Skip to content

Add SKU or ID to NoSuchEntityException in ProductRepository #40096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: 2.4-develop
Choose a base branch
from
4 changes: 2 additions & 2 deletions app/code/Magento/Catalog/Model/ProductRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ public function get($sku, $editMode = false, $storeId = null, $forceReload = fal
$productId = $this->resourceModel->getIdBySku($sku);
if (!$productId) {
throw new NoSuchEntityException(
__("The product that was requested doesn't exist. Verify the product and try again.")
__("The product with SKU \"%1\" does not exist.", $sku)
);
}
if ($editMode) {
Expand Down Expand Up @@ -319,7 +319,7 @@ public function getById($productId, $editMode = false, $storeId = null, $forceRe
$product->load($productId);
if (!$product->getId()) {
throw new NoSuchEntityException(
__("The product that was requested doesn't exist. Verify the product and try again.")
__("The product with ID \"%1\" does not exist.", $productId)
);
}
$this->cacheProduct($cacheKey, $product);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
*/
class ManagementTest extends TestCase
{
const STUB_PRODUCT_SKU_1 = 'Simple Product 1';
const STUB_PRODUCT_SKU_2 = 'Simple Product 2';
const STUB_PRODUCT_TYPE = 'simple';
const STUB_LINK_TYPE = 'related';
const STUB_BAD_TYPE = 'bad type';
private const STUB_PRODUCT_SKU_1 = 'Simple Product 1';
private const STUB_PRODUCT_SKU_2 = 'Simple Product 2';
private const STUB_PRODUCT_TYPE = 'simple';
private const STUB_LINK_TYPE = 'related';
private const STUB_BAD_TYPE = 'bad type';

/**
* @var Management
Expand Down Expand Up @@ -289,13 +289,13 @@ public function testSetProductLinksNoProductException()
->method('get')
->willThrowException(
new NoSuchEntityException(
__("The product that was requested doesn't exist. Verify the product and try again.")
__('The product with SKU "' . $productSku . '" does not exist.')
)
);

$this->expectException(NoSuchEntityException::class);
$this->expectExceptionMessage(
"The product that was requested doesn't exist. Verify the product and try again."
'The product with SKU "' . $productSku . '" does not exist.'
);

$this->model->setProductLinks($productSku, $links);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ public function testGetAbsentProduct(): void
{
$this->expectException('Magento\Framework\Exception\NoSuchEntityException');
$this->expectExceptionMessage(
'The product that was requested doesn\'t exist. Verify the product and try again.'
'The product with SKU "test_sku" does not exist.'
);
$this->productFactory->expects($this->once())->method('create')
->willReturn($this->product);
Expand Down Expand Up @@ -521,7 +521,7 @@ public function testGetByIdAbsentProduct(): void
{
$this->expectException('Magento\Framework\Exception\NoSuchEntityException');
$this->expectExceptionMessage(
'The product that was requested doesn\'t exist. Verify the product and try again.'
'The product with ID "product_id" does not exist.'
);
$this->productFactory->expects($this->once())->method('create')
->willReturn($this->product);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,18 +492,22 @@ public function testCreateThrowsExceptionIfProvidedImageHasWrongMimeType()
$this->_webApiCall($this->createServiceInfo, ['sku' => 'simple', 'entry' => $requestData]);
}

protected function assertProductNotFoundException(\Exception $e, string $sku): void
{
$decoded = json_decode($e->getMessage(), true);
$this->assertEquals('The product with SKU "%1" does not exist.', $decoded['message']);
$this->assertContains($sku, $decoded['parameters']);
$this->assertEquals(404, $e->getCode());
}

/**
* Test create method if target product does not exist
*
*/
public function testCreateThrowsExceptionIfTargetProductDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage(
'The product that was requested doesn\'t exist. Verify the product and try again.'
);
$sku = 'wrong_product_sku';

$this->createServiceInfo['rest']['resourcePath'] = '/V1/products/wrong_product_sku/media';
$this->createServiceInfo['rest']['resourcePath'] = '/V1/products/' . $sku . '/media';

$requestData = [
'id' => null,
Expand All @@ -519,7 +523,12 @@ public function testCreateThrowsExceptionIfTargetProductDoesNotExist()
]
];

$this->_webApiCall($this->createServiceInfo, ['sku' => 'simple', 'entry' => $requestData]);
try {
$this->_webApiCall($this->createServiceInfo, ['sku' => $sku, 'entry' => $requestData]);
$this->fail('Expected exception was not thrown.');
} catch (\Exception $e) {
$this->assertProductNotFoundException($e, $sku);
}
}

/**
Expand Down Expand Up @@ -551,19 +560,14 @@ public function testCreateThrowsExceptionIfProvidedImageNameContainsForbiddenCha

/**
* Test update() method if target product does not exist
*
*/
public function testUpdateThrowsExceptionIfTargetProductDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage(
'The product that was requested doesn\'t exist. Verify the product and try again.'
);
$sku = 'wrong_product_sku';

$this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/wrong_product_sku/media'
. '/' . 'wrong-sku';
$this->updateServiceInfo['rest']['resourcePath'] = '/V1/products/' . $sku . '/media/' . 'wrong-sku';
$requestData = [
'sku' => 'wrong_product_sku',
'sku' => $sku,
'entry' => [
'id' => 9999,
'media_type' => 'image',
Expand All @@ -574,9 +578,15 @@ public function testUpdateThrowsExceptionIfTargetProductDoesNotExist()
],
];

$this->_webApiCall($this->updateServiceInfo, $requestData, null, 'all');
try {
$this->_webApiCall($this->updateServiceInfo, $requestData, null, 'all');
$this->fail('Expected exception was not thrown.');
} catch (\Exception $e) {
$this->assertProductNotFoundException($e, $sku);
}
}


/**
* Test update() method if there is no image with given id
*
Expand Down Expand Up @@ -607,22 +617,23 @@ public function testUpdateThrowsExceptionIfThereIsNoImageWithGivenId()

/**
* Test delete() method if target product does not exist
*
*/
public function testDeleteThrowsExceptionIfTargetProductDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage(
'The product that was requested doesn\'t exist. Verify the product and try again.'
);
$sku = 'wrong_product_sku';

$this->deleteServiceInfo['rest']['resourcePath'] = '/V1/products/wrong_product_sku/media/9999';
$this->deleteServiceInfo['rest']['resourcePath'] = '/V1/products/' . $sku . '/media/9999';
$requestData = [
'sku' => 'wrong_product_sku',
'sku' => $sku,
'entryId' => 9999,
];

$this->_webApiCall($this->deleteServiceInfo, $requestData);
try {
$this->_webApiCall($this->deleteServiceInfo, $requestData);
$this->fail('Expected exception was not thrown.');
} catch (\Exception $e) {
$this->assertProductNotFoundException($e, $sku);
}
}

/**
Expand Down Expand Up @@ -778,7 +789,7 @@ public function testGetListForAbsentSku()
if (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
$this->expectException('SoapFault');
$this->expectExceptionMessage(
"The product that was requested doesn't exist. Verify the product and try again."
"The product with SKU \"%1\" does not exist."
);
} else {
$this->expectException('Exception');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ public function testUpdateNegative($optionData, $message, $exceptionCode)
{
$this->_markTestAsRestOnly();
$productSku = 'simple';

/** @var ProductRepository $productRepository */
$productRepository = $this->objectManager->create(ProductRepository::class);
$options = $productRepository->get($productSku, true)->getOptions();
Expand All @@ -434,10 +435,14 @@ public function testUpdateNegative($optionData, $message, $exceptionCode)
],
];

$this->expectException('Exception');
$this->expectExceptionMessage($message);
$this->expectExceptionCode($exceptionCode);
$this->_webApiCall($serviceInfo, ['option' => $optionData]);
try {
$this->_webApiCall($serviceInfo, ['option' => $optionData]);
$this->fail('Expected exception was not thrown.');
} catch (\Exception $e) {
$this->assertEquals($exceptionCode, $e->getCode());
$this->assertStringContainsString($message, $e->getMessage());
$this->assertStringContainsString($productSku, $e->getMessage());
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* Copyright 2025 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

namespace Magento\Catalog\Api;

use Magento\Catalog\Api\Data\ProductInterface;

/**
* Test for \Magento\Catalog\Api\ProductRepositoryInterface category links
*
* @magentoAppIsolation enabled
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ProductRepositoryCategoryLinksTest extends ProductRepositoryInterfaceTest
{
private const KEY_CATEGORY_LINKS = 'category_links';

/**
* Test product category links
*
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
*/
public function testProductCategoryLinks()
{
// Create simple product
$productData = $this->getSimpleProductData();
$productData[ProductInterface::EXTENSION_ATTRIBUTES_KEY] = [
self::KEY_CATEGORY_LINKS => [['category_id' => 333, 'position' => 0]],
];
$response = $this->saveProduct($productData);
$this->assertEquals(
[['category_id' => 333, 'position' => 0]],
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS]
);
$response = $this->getProduct($productData[ProductInterface::SKU]);
$this->assertArrayHasKey(ProductInterface::EXTENSION_ATTRIBUTES_KEY, $response);
$extensionAttributes = $response[ProductInterface::EXTENSION_ATTRIBUTES_KEY];
$this->assertArrayHasKey(self::KEY_CATEGORY_LINKS, $extensionAttributes);
$this->assertEquals([['category_id' => 333, 'position' => 0]], $extensionAttributes[self::KEY_CATEGORY_LINKS]);
}

/**
* Test update product category without categories
*
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
*/
public function testUpdateProductCategoryLinksNullOrNotExists()
{
$response = $this->getProduct('simple333');
// update product without category_link or category_link is null
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS] = null;
$response = $this->updateProduct($response);
$this->assertEquals(
[['category_id' => 333, 'position' => 0]],
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS]
);
unset($response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS]);
$response = $this->updateProduct($response);
$this->assertEquals(
[['category_id' => 333, 'position' => 0]],
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS]
);
}

/**
* Test update product category links position
*
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
*/
public function testUpdateProductCategoryLinksPosition()
{
$response = $this->getProduct('simple333');
// update category_link position
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS] = [
['category_id' => 333, 'position' => 10],
];
$response = $this->updateProduct($response);
$this->assertEquals(
[['category_id' => 333, 'position' => 10]],
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS]
);
}

/**
* Test update product category links unassing
*
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
*/
public function testUpdateProductCategoryLinksUnassign()
{
$response = $this->getProduct('simple333');
// unassign category_links from product
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY][self::KEY_CATEGORY_LINKS] = [];
$response = $this->updateProduct($response);
$this->assertArrayNotHasKey(
self::KEY_CATEGORY_LINKS,
$response[ProductInterface::EXTENSION_ATTRIBUTES_KEY]
);
}
}
Loading