ItemTest.php 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Quote\Test\Unit\Model\Quote;
  7. /**
  8. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  9. */
  10. class ItemTest extends \PHPUnit\Framework\TestCase
  11. {
  12. /**
  13. * @var \Magento\Quote\Model\Quote\Item
  14. */
  15. private $model;
  16. /**
  17. * @var \Magento\Framework\Locale\FormatInterface
  18. */
  19. private $localeFormat;
  20. /**
  21. * @var \Magento\Framework\Model\Context
  22. */
  23. private $modelContext;
  24. /**
  25. * @var \Magento\Framework\Event\ManagerInterface
  26. */
  27. private $eventDispatcher;
  28. /**
  29. * @var \Magento\Sales\Model\Status\ListStatus
  30. */
  31. private $errorInfos;
  32. /**
  33. * @var \Magento\Quote\Model\Quote\Item\OptionFactory
  34. */
  35. private $itemOptionFactory;
  36. /**
  37. * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
  38. */
  39. private $objectManagerHelper;
  40. /**
  41. * @var \Magento\Quote\Model\Quote\Item\Compare|\PHPUnit_Framework_MockObject_MockObject
  42. */
  43. protected $compareHelper;
  44. /** @var \PHPUnit_Framework_MockObject_MockObject */
  45. protected $stockItemMock;
  46. /**
  47. * @var \Magento\Framework\Serialize\Serializer\Json
  48. */
  49. private $serializer;
  50. const PRODUCT_ID = 1;
  51. const PRODUCT_TYPE = 'simple';
  52. const PRODUCT_SKU = '12345';
  53. const PRODUCT_NAME = 'test_product';
  54. const PRODUCT_WEIGHT = '1lb';
  55. const PRODUCT_TAX_CLASS_ID = 3;
  56. const PRODUCT_COST = '9.00';
  57. protected function setUp()
  58. {
  59. $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  60. $this->localeFormat = $this->getMockBuilder(\Magento\Framework\Locale\FormatInterface::class)
  61. ->disableOriginalConstructor()
  62. ->getMock();
  63. $this->modelContext = $this->getMockBuilder(\Magento\Framework\Model\Context::class)
  64. ->disableOriginalConstructor()
  65. ->setMethods(['getEventDispatcher'])
  66. ->getMock();
  67. $this->eventDispatcher = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class)
  68. ->disableOriginalConstructor()
  69. ->setMethods(['dispatch'])
  70. ->getMock();
  71. $this->modelContext->expects($this->any())
  72. ->method('getEventDispatcher')
  73. ->will($this->returnValue($this->eventDispatcher));
  74. $this->errorInfos = $this->getMockBuilder(\Magento\Sales\Model\Status\ListStatus::class)
  75. ->disableOriginalConstructor()
  76. ->setMethods(['clear', 'addItem', 'getItems', 'removeItemsByParams'])
  77. ->getMock();
  78. $statusListFactory = $this->getMockBuilder(\Magento\Sales\Model\Status\ListFactory::class)
  79. ->disableOriginalConstructor()
  80. ->setMethods(['create'])
  81. ->getMock();
  82. $statusListFactory->expects($this->any())
  83. ->method('create')
  84. ->will($this->returnValue($this->errorInfos));
  85. $this->itemOptionFactory = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\OptionFactory::class)
  86. ->disableOriginalConstructor()
  87. ->setMethods(['create'])
  88. ->getMock();
  89. $this->compareHelper = $this->createMock(\Magento\Quote\Model\Quote\Item\Compare::class);
  90. $this->stockItemMock = $this->createPartialMock(
  91. \Magento\CatalogInventory\Model\Stock\Item::class,
  92. ['getIsQtyDecimal', '__wakeup']
  93. );
  94. $this->serializer = $this->getMockBuilder(\Magento\Framework\Serialize\Serializer\Json::class)
  95. ->setMethods(['unserialize'])
  96. ->getMockForAbstractClass();
  97. $this->model = $this->objectManagerHelper->getObject(
  98. \Magento\Quote\Model\Quote\Item::class,
  99. [
  100. 'localeFormat' => $this->localeFormat,
  101. 'context' => $this->modelContext,
  102. 'statusListFactory' => $statusListFactory,
  103. 'itemOptionFactory' => $this->itemOptionFactory,
  104. 'quoteItemCompare' => $this->compareHelper,
  105. 'serializer' => $this->serializer
  106. ]
  107. );
  108. }
  109. public function testGetAddress()
  110. {
  111. $quote = $this->getMockBuilder(\Magento\Quote\Model\Quote::class)
  112. ->setMethods(['getShippingAddress', 'getBillingAddress', 'getStoreId', '__wakeup'])
  113. ->disableOriginalConstructor()
  114. ->getMock();
  115. $quote->expects($this->once())
  116. ->method('getShippingAddress')
  117. ->will($this->returnValue('shipping'));
  118. $quote->expects($this->once())
  119. ->method('getBillingAddress')
  120. ->will($this->returnValue('billing'));
  121. $quote->expects($this->any())
  122. ->method('getStoreId')
  123. ->will($this->returnValue(1));
  124. $this->model->setQuote($quote);
  125. $quote->setItemsQty(2);
  126. $quote->setVirtualItemsQty(1);
  127. $this->assertEquals('shipping', $this->model->getAddress(), 'Wrong shipping address');
  128. $quote->setItemsQty(2);
  129. $quote->setVirtualItemsQty(2);
  130. $this->assertEquals('billing', $this->model->getAddress(), 'Wrong billing address');
  131. }
  132. public function testSetAndQuote()
  133. {
  134. $idValue = "id_value";
  135. $quote = $this->getMockBuilder(\Magento\Quote\Model\Quote::class)
  136. ->setMethods(['getId', 'getStoreId', '__wakeup'])
  137. ->disableOriginalConstructor()
  138. ->getMock();
  139. $quote->expects($this->once())
  140. ->method('getId')
  141. ->will($this->returnValue($idValue));
  142. $quote->expects($this->any())
  143. ->method('getStoreId')
  144. ->will($this->returnValue(1));
  145. $this->model->setQuote($quote);
  146. $this->assertSame($quote, $this->model->getQuote());
  147. $this->assertEquals($idValue, $this->model->getQuoteId());
  148. }
  149. /**
  150. * Tests that adding a quantity to an item without a parent item or an id will add additional quantity.
  151. */
  152. public function testAddQtyNormal()
  153. {
  154. $existingQuantity = 2;
  155. $quantityToAdd = 3;
  156. $preparedQuantityToAdd = 4;
  157. $this->model->setData('qty', $existingQuantity);
  158. $this->localeFormat->expects($this->at(0))
  159. ->method('getNumber')
  160. ->with($quantityToAdd)
  161. ->will($this->returnValue($preparedQuantityToAdd));
  162. $this->localeFormat->expects($this->at(1))
  163. ->method('getNumber')
  164. ->with($preparedQuantityToAdd + $existingQuantity)
  165. ->will($this->returnValue($preparedQuantityToAdd + $existingQuantity));
  166. $this->model->addQty($quantityToAdd);
  167. $this->assertEquals($preparedQuantityToAdd, $this->model->getQtyToAdd());
  168. $this->assertEquals($preparedQuantityToAdd + $existingQuantity, $this->model->getQty());
  169. }
  170. /**
  171. * Tests that adding a quantity to an item with a parent item and an id will not change the quantity.
  172. */
  173. public function testAddQtyExistingParentItemAndId()
  174. {
  175. $existingQuantity = 2;
  176. $quantityToAdd = 3;
  177. $parentItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class)
  178. ->setMethods(['addChild', '__wakeup'])
  179. ->disableOriginalConstructor()
  180. ->getMock();
  181. $this->model->setParentItem($parentItemMock);
  182. $this->model->setId(1);
  183. $this->model->setData('qty', $existingQuantity);
  184. $this->model->addQty($quantityToAdd);
  185. $this->assertEquals($existingQuantity, $this->model->getQty());
  186. $this->assertNull($this->model->getQtyToAdd());
  187. }
  188. public function testSetQty()
  189. {
  190. $existingQuantity = 2;
  191. $quantityToAdd = 3;
  192. $preparedQuantityToAdd = 4;
  193. $this->localeFormat->expects($this->once())
  194. ->method('getNumber')
  195. ->with($quantityToAdd)
  196. ->will($this->returnValue($preparedQuantityToAdd));
  197. $this->model->setData('qty', $existingQuantity);
  198. $this->eventDispatcher->expects($this->once())
  199. ->method('dispatch')
  200. ->with('sales_quote_item_qty_set_after', ['item' => $this->model]);
  201. $this->model->setQty($quantityToAdd);
  202. $this->assertEquals($preparedQuantityToAdd, $this->model->getQty());
  203. }
  204. public function testSetQtyQuoteIgnoreOldQuantity()
  205. {
  206. $existingQuantity = 2;
  207. $quantityToAdd = 3;
  208. $preparedQuantityToAdd = 4;
  209. $this->localeFormat->expects($this->once())
  210. ->method('getNumber')
  211. ->with($quantityToAdd)
  212. ->will($this->returnValue($preparedQuantityToAdd));
  213. $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class)
  214. ->disableOriginalConstructor()
  215. ->setMethods(['getIgnoreOldQty', 'getStoreId', '__wakeup'])
  216. ->getMock();
  217. $quoteMock->expects($this->once())
  218. ->method('getIgnoreOldQty')
  219. ->will($this->returnValue(true));
  220. $quoteMock->expects($this->any())
  221. ->method('getStoreId')
  222. ->will($this->returnValue(1));
  223. $this->model->setQuote($quoteMock);
  224. $this->model->setData('qty', $existingQuantity);
  225. $this->eventDispatcher->expects($this->once())
  226. ->method('dispatch')
  227. ->with('sales_quote_item_qty_set_after', ['item' => $this->model]);
  228. $this->model->setQty($quantityToAdd);
  229. $this->assertEquals($preparedQuantityToAdd, $this->model->getQty());
  230. }
  231. public function testSetQtyUseOldQuantity()
  232. {
  233. $existingQuantity = 2;
  234. $quantityToAdd = 3;
  235. $preparedQuantityToAdd = 4;
  236. $this->localeFormat->expects($this->once())
  237. ->method('getNumber')
  238. ->with($quantityToAdd)
  239. ->will($this->returnValue($preparedQuantityToAdd));
  240. $this->model->setData('qty', $existingQuantity);
  241. $this->model->setUseOldQty(true);
  242. $this->eventDispatcher->expects($this->once())
  243. ->method('dispatch')
  244. ->with('sales_quote_item_qty_set_after', ['item' => $this->model]);
  245. $this->model->setQty($quantityToAdd);
  246. $this->assertEquals($existingQuantity, $this->model->getQty());
  247. }
  248. public function testSetQtyOptions()
  249. {
  250. $value = ['a' => 'b'];
  251. $this->model->setQtyOptions($value);
  252. $this->assertEquals($value, $this->model->getQtyOptions());
  253. }
  254. public function testSetProduct()
  255. {
  256. $productMock = $this->generateProductMock(
  257. self::PRODUCT_ID,
  258. self::PRODUCT_TYPE,
  259. self::PRODUCT_SKU,
  260. self::PRODUCT_NAME,
  261. self::PRODUCT_WEIGHT,
  262. self::PRODUCT_TAX_CLASS_ID,
  263. self::PRODUCT_COST
  264. );
  265. $this->eventDispatcher->expects($this->once())
  266. ->method('dispatch')
  267. ->with('sales_quote_item_set_product', ['product' => $productMock, 'quote_item' => $this->model]);
  268. $this->model->setProduct($productMock);
  269. $this->assertEquals($productMock, $this->model->getProduct());
  270. $this->assertEquals(self::PRODUCT_ID, $this->model->getProductId());
  271. $this->assertEquals(self::PRODUCT_TYPE, $this->model->getData('product_type'));
  272. $this->assertEquals(self::PRODUCT_SKU, $this->model->getSku());
  273. $this->assertEquals(self::PRODUCT_NAME, $this->model->getName());
  274. $this->assertEquals(self::PRODUCT_WEIGHT, $this->model->getWeight());
  275. $this->assertEquals(self::PRODUCT_TAX_CLASS_ID, $this->model->getTaxClassId());
  276. $this->assertEquals(self::PRODUCT_COST, $this->model->getBaseCost());
  277. $this->assertNull($this->model->getIsQtyDecimal());
  278. }
  279. public function testSetProductWithQuoteAndStockItem()
  280. {
  281. $productMock = $this->generateProductMock(
  282. self::PRODUCT_ID,
  283. self::PRODUCT_TYPE,
  284. self::PRODUCT_SKU,
  285. self::PRODUCT_NAME,
  286. self::PRODUCT_WEIGHT,
  287. self::PRODUCT_TAX_CLASS_ID,
  288. self::PRODUCT_COST
  289. );
  290. $this->eventDispatcher->expects($this->once())
  291. ->method('dispatch')
  292. ->with('sales_quote_item_set_product', ['product' => $productMock, 'quote_item' => $this->model]);
  293. $isQtyDecimal = true;
  294. $this->stockItemMock->expects($this->once())
  295. ->method('getIsQtyDecimal')
  296. ->will($this->returnValue($isQtyDecimal));
  297. $storeId = 15;
  298. $customerGroupId = 11;
  299. $quoteMock = $this->getMockBuilder(\Magento\Quote\Model\Quote::class)
  300. ->disableOriginalConstructor()
  301. ->setMethods(['getStoreId', 'getCustomerGroupId', '__wakeup'])
  302. ->getMock();
  303. $quoteMock->expects($this->any())
  304. ->method('getStoreId')
  305. ->will($this->returnValue($storeId));
  306. $quoteMock->expects($this->once())
  307. ->method('getCustomerGroupId')
  308. ->will($this->returnValue($customerGroupId));
  309. $this->model->setQuote($quoteMock);
  310. $productMock->expects($this->once())
  311. ->method('setStoreId')
  312. ->with($storeId);
  313. $productMock->expects($this->once())
  314. ->method('setCustomerGroupId')
  315. ->with($customerGroupId);
  316. $this->model->setProduct($productMock);
  317. $this->assertEquals($productMock, $this->model->getProduct());
  318. $this->assertEquals(self::PRODUCT_ID, $this->model->getProductId());
  319. $this->assertEquals(self::PRODUCT_TYPE, $this->model->getRealProductType());
  320. $this->assertEquals(self::PRODUCT_SKU, $this->model->getSku());
  321. $this->assertEquals(self::PRODUCT_NAME, $this->model->getName());
  322. $this->assertEquals(self::PRODUCT_WEIGHT, $this->model->getWeight());
  323. $this->assertEquals(self::PRODUCT_TAX_CLASS_ID, $this->model->getTaxClassId());
  324. $this->assertEquals(self::PRODUCT_COST, $this->model->getBaseCost());
  325. $this->assertEquals($isQtyDecimal, $this->model->getIsQtyDecimal());
  326. }
  327. /**
  328. * Generate product mock.
  329. *
  330. * @param int $productId
  331. * @param string $productType
  332. * @param string $productSku
  333. * @param string $productName
  334. * @param string $productWeight
  335. * @param int $productTaxClassId
  336. * @param float $productCost
  337. * @return \PHPUnit_Framework_MockObject_MockObject
  338. */
  339. private function generateProductMock(
  340. $productId,
  341. $productType,
  342. $productSku,
  343. $productName,
  344. $productWeight,
  345. $productTaxClassId,
  346. $productCost
  347. ) {
  348. $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
  349. ->disableOriginalConstructor()
  350. ->setMethods(
  351. [
  352. 'getId',
  353. 'getTypeId',
  354. 'getSku',
  355. 'getName',
  356. 'getWeight',
  357. 'getTaxClassId',
  358. 'getCost',
  359. 'setStoreId',
  360. 'setCustomerGroupId',
  361. 'getTypeInstance',
  362. 'getStickWithinParent',
  363. 'getCustomOptions',
  364. 'getExtensionAttributes',
  365. 'toArray',
  366. '__wakeup',
  367. 'getStore',
  368. ]
  369. )
  370. ->getMock();
  371. $productMock->expects($this->any())
  372. ->method('getId')
  373. ->will($this->returnValue($productId));
  374. $productMock->expects($this->any())
  375. ->method('getTypeId')
  376. ->will($this->returnValue($productType));
  377. $productMock->expects($this->any())
  378. ->method('getSku')
  379. ->will($this->returnValue($productSku));
  380. $productMock->expects($this->any())
  381. ->method('getName')
  382. ->will($this->returnValue($productName));
  383. $productMock->expects($this->any())
  384. ->method('getWeight')
  385. ->will($this->returnValue($productWeight));
  386. $productMock->expects($this->any())
  387. ->method('getTaxClassId')
  388. ->will($this->returnValue($productTaxClassId));
  389. $productMock->expects($this->any())
  390. ->method('getCost')
  391. ->will($this->returnValue($productCost));
  392. $store = $this->createPartialMock(\Magento\Store\Model\Store::class, ['getWebsiteId']);
  393. $store->expects($this->any())
  394. ->method('getWebsiteId')
  395. ->will($this->returnValue(10));
  396. $productMock->expects($this->any())
  397. ->method('getStore')
  398. ->will($this->returnValue($store));
  399. $extensionAttribute = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductExtensionInterface::class)
  400. ->setMethods(['getStockItem'])
  401. ->disableOriginalConstructor()
  402. ->getMockForAbstractClass();
  403. $extensionAttribute->expects($this->atLeastOnce())
  404. ->method('getStockItem')
  405. ->will($this->returnValue($this->stockItemMock));
  406. $productMock->expects($this->atLeastOnce())->method('getExtensionAttributes')->willReturn($extensionAttribute);
  407. return $productMock;
  408. }
  409. public function testRepresentProductNoProduct()
  410. {
  411. $productMock = $this->generateProductMock(
  412. self::PRODUCT_ID,
  413. self::PRODUCT_TYPE,
  414. self::PRODUCT_SKU,
  415. self::PRODUCT_NAME,
  416. self::PRODUCT_WEIGHT,
  417. self::PRODUCT_TAX_CLASS_ID,
  418. self::PRODUCT_COST
  419. );
  420. $this->model->setProduct($productMock);
  421. $this->assertFalse($this->model->representProduct(null));
  422. }
  423. public function testRepresentProductStickWithinParentNotSameAsParentItem()
  424. {
  425. $productMock = $this->generateProductMock(
  426. self::PRODUCT_ID,
  427. self::PRODUCT_TYPE,
  428. self::PRODUCT_SKU,
  429. self::PRODUCT_NAME,
  430. self::PRODUCT_WEIGHT,
  431. self::PRODUCT_TAX_CLASS_ID,
  432. self::PRODUCT_COST
  433. );
  434. $parentItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class)
  435. ->setMethods(['addChild', '__wakeup'])
  436. ->disableOriginalConstructor()
  437. ->getMock();
  438. $this->model->setProduct($productMock);
  439. $this->model->setParentItem($parentItemMock);
  440. $productMock->expects($this->once())
  441. ->method('getStickWithinParent')
  442. ->will($this->returnValue(true));
  443. $this->assertFalse($this->model->representProduct($productMock));
  444. }
  445. public function testRepresentProductItemOptionsNotInProductOptions()
  446. {
  447. $productMock = $this->generateProductMock(
  448. self::PRODUCT_ID,
  449. self::PRODUCT_TYPE,
  450. self::PRODUCT_SKU,
  451. self::PRODUCT_NAME,
  452. self::PRODUCT_WEIGHT,
  453. self::PRODUCT_TAX_CLASS_ID,
  454. self::PRODUCT_COST
  455. );
  456. $parentItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class)
  457. ->setMethods(['addChild', '__wakeup'])
  458. ->disableOriginalConstructor()
  459. ->getMock();
  460. $this->model->setProduct($productMock);
  461. $this->model->setParentItem($parentItemMock);
  462. $optionCode1 = 1234;
  463. $optionMock1 = $this->createOptionMock($optionCode1);
  464. $optionMock1->expects($this->any())
  465. ->method('getValue')
  466. ->will($this->returnValue(1234));
  467. $optionCode2 = 7890;
  468. $optionMock2 = $this->createOptionMock($optionCode2);
  469. $optionMock2->expects($this->any())
  470. ->method('getValue')
  471. ->will($this->returnValue(7890));
  472. $this->model->setOptions([$optionMock1, $optionMock2]);
  473. $productMock->expects($this->once())
  474. ->method('getStickWithinParent')
  475. ->will($this->returnValue($parentItemMock));
  476. $productMock->expects($this->once())
  477. ->method('getCustomOptions')
  478. ->will($this->returnValue([$optionCode1 => $optionMock1]));
  479. $this->assertFalse($this->model->representProduct($productMock));
  480. }
  481. public function testRepresentProductProductOptionsNotInItemOptions()
  482. {
  483. $productMock = $this->generateProductMock(
  484. self::PRODUCT_ID,
  485. self::PRODUCT_TYPE,
  486. self::PRODUCT_SKU,
  487. self::PRODUCT_NAME,
  488. self::PRODUCT_WEIGHT,
  489. self::PRODUCT_TAX_CLASS_ID,
  490. self::PRODUCT_COST
  491. );
  492. $parentItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class)
  493. ->setMethods(['addChild', '__wakeup'])
  494. ->disableOriginalConstructor()
  495. ->getMock();
  496. $this->model->setProduct($productMock);
  497. $this->model->setParentItem($parentItemMock);
  498. $optionCode1 = 1234;
  499. $optionMock1 = $this->createOptionMock($optionCode1);
  500. $optionMock1->expects($this->any())
  501. ->method('getValue')
  502. ->will($this->returnValue(1234));
  503. $optionCode2 = 7890;
  504. $optionMock2 = $this->createOptionMock($optionCode2);
  505. $optionMock2->expects($this->any())
  506. ->method('getValue')
  507. ->will($this->returnValue(7890));
  508. $this->model->setOptions([$optionMock1]);
  509. $productMock->expects($this->once())
  510. ->method('getStickWithinParent')
  511. ->will($this->returnValue($parentItemMock));
  512. $productMock->expects($this->once())
  513. ->method('getCustomOptions')
  514. ->will($this->returnValue([$optionCode1 => $optionMock1, $optionCode2 => $optionMock2]));
  515. $this->assertFalse($this->model->representProduct($productMock));
  516. }
  517. public function testRepresentProductTrue()
  518. {
  519. $productMock = $this->generateProductMock(
  520. self::PRODUCT_ID,
  521. self::PRODUCT_TYPE,
  522. self::PRODUCT_SKU,
  523. self::PRODUCT_NAME,
  524. self::PRODUCT_WEIGHT,
  525. self::PRODUCT_TAX_CLASS_ID,
  526. self::PRODUCT_COST
  527. );
  528. $parentItemMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class)
  529. ->setMethods(['addChild', '__wakeup'])
  530. ->disableOriginalConstructor()
  531. ->getMock();
  532. $this->model->setProduct($productMock);
  533. $this->model->setParentItem($parentItemMock);
  534. $optionCode1 = 1234;
  535. $optionMock1 = $this->createOptionMock($optionCode1);
  536. $optionMock1->expects($this->any())
  537. ->method('getValue')
  538. ->will($this->returnValue(1234));
  539. $optionCode2 = 7890;
  540. $optionMock2 = $this->createOptionMock($optionCode2);
  541. $optionMock2->expects($this->any())
  542. ->method('getValue')
  543. ->will($this->returnValue(7890));
  544. $this->model->setOptions([$optionMock1, $optionMock2]);
  545. $productMock->expects($this->once())
  546. ->method('getStickWithinParent')
  547. ->will($this->returnValue($parentItemMock));
  548. $productMock->expects($this->once())
  549. ->method('getCustomOptions')
  550. ->will($this->returnValue([$optionCode1 => $optionMock1, $optionCode2 => $optionMock2]));
  551. $this->assertTrue($this->model->representProduct($productMock));
  552. }
  553. /**
  554. * test compare
  555. */
  556. public function testCompare()
  557. {
  558. $itemMock = $this->createMock(\Magento\Quote\Model\Quote\Item::class);
  559. $this->compareHelper->expects($this->once())
  560. ->method('compare')
  561. ->with($this->equalTo($this->model), $this->equalTo($itemMock))
  562. ->will($this->returnValue(true));
  563. $this->assertTrue($this->model->compare($itemMock));
  564. }
  565. public function testCompareOptionsEqual()
  566. {
  567. $optionCode1 = 1234;
  568. $optionMock1 = $this->createOptionMock($optionCode1);
  569. $optionMock1->expects($this->any())
  570. ->method('getValue')
  571. ->will($this->returnValue(1234));
  572. $this->assertTrue(
  573. $this->model->compareOptions([$optionCode1 => $optionMock1], [$optionCode1 => $optionMock1])
  574. );
  575. }
  576. public function testCompareOptionsDifferentValues()
  577. {
  578. $optionCode1 = 1234;
  579. $optionMock1 = $this->createOptionMock($optionCode1);
  580. $optionMock1->expects($this->any())
  581. ->method('getValue')
  582. ->will($this->returnValue(1234));
  583. $optionCode2 = 1234;
  584. $optionMock2 = $this->createOptionMock($optionCode1);
  585. $optionMock2->expects($this->any())
  586. ->method('getValue')
  587. ->will($this->returnValue(7890));
  588. $this->assertFalse(
  589. $this->model->compareOptions([$optionCode1 => $optionMock1], [$optionCode2 => $optionMock2])
  590. );
  591. }
  592. public function testCompareOptionsNullValues()
  593. {
  594. $optionCode1 = 1234;
  595. $optionMock1 = $this->createOptionMock($optionCode1);
  596. $optionMock1->expects($this->any())
  597. ->method('getValue')
  598. ->will($this->returnValue(1234));
  599. $optionCode2 = 1234;
  600. $optionMock2 = $this->createOptionMock($optionCode1);
  601. $optionMock2->expects($this->any())
  602. ->method('getValue')
  603. ->will($this->returnValue(null));
  604. $this->assertFalse(
  605. $this->model->compareOptions([$optionCode1 => $optionMock1], [$optionCode2 => $optionMock2])
  606. );
  607. }
  608. public function testCompareOptionsMultipleEquals()
  609. {
  610. $optionCode1 = 1234;
  611. $optionMock1 = $this->createOptionMock($optionCode1);
  612. $optionMock1->expects($this->any())
  613. ->method('getValue')
  614. ->will($this->returnValue(1234));
  615. $optionCode2 = 7890;
  616. $optionMock2 = $this->createOptionMock($optionCode1);
  617. $optionMock2->expects($this->any())
  618. ->method('getValue')
  619. ->will($this->returnValue(7890));
  620. $this->assertFalse(
  621. $this->model->compareOptions(
  622. [$optionCode1 => $optionMock1, $optionCode2 => $optionMock2],
  623. [$optionCode1 => $optionMock1, $optionCode2 => $optionMock2]
  624. )
  625. );
  626. }
  627. public function testGetQtyOptions()
  628. {
  629. $optionCode1 = 1234;
  630. $optionMock1 = $this->createOptionMock($optionCode1);
  631. $productMock = $this->generateProductMock(
  632. self::PRODUCT_ID,
  633. self::PRODUCT_TYPE,
  634. self::PRODUCT_SKU,
  635. self::PRODUCT_NAME,
  636. self::PRODUCT_WEIGHT,
  637. self::PRODUCT_TAX_CLASS_ID,
  638. self::PRODUCT_COST
  639. );
  640. $optionMock1->expects($this->any())
  641. ->method('getProduct')
  642. ->will($this->returnValue($productMock));
  643. $optionCode2 = 'product_qty_' . self::PRODUCT_ID;
  644. $optionMock2 = $this->createOptionMock($optionCode2);
  645. $productMock2 = $this->generateProductMock(
  646. self::PRODUCT_ID + 1,
  647. self::PRODUCT_TYPE,
  648. self::PRODUCT_SKU,
  649. self::PRODUCT_NAME,
  650. self::PRODUCT_WEIGHT,
  651. self::PRODUCT_TAX_CLASS_ID,
  652. self::PRODUCT_COST
  653. );
  654. $this->model->setProduct($productMock);
  655. $this->model->setProduct($productMock2);
  656. $this->model->setOptions([$optionCode1 => $optionMock1, $optionCode2 => $optionMock2]);
  657. $this->assertEquals([self::PRODUCT_ID => $optionMock2], $this->model->getQtyOptions());
  658. }
  659. public function testToArray()
  660. {
  661. $productMock = $this->generateProductMock(
  662. self::PRODUCT_ID,
  663. self::PRODUCT_TYPE,
  664. self::PRODUCT_SKU,
  665. self::PRODUCT_NAME,
  666. self::PRODUCT_WEIGHT,
  667. self::PRODUCT_TAX_CLASS_ID,
  668. self::PRODUCT_COST
  669. );
  670. $this->model->setProduct($productMock);
  671. $toArrayValue = ['a' => 'b'];
  672. $productMock->expects($this->once())
  673. ->method('toArray')
  674. ->will($this->returnValue($toArrayValue));
  675. $data = $this->model->toArray();
  676. $this->assertEquals($toArrayValue, $data['product']);
  677. }
  678. public function testGetProductTypeOption()
  679. {
  680. $optionProductType = 'product_type';
  681. $optionProductTypeValue = 'abcd';
  682. $optionMock = $this->createOptionMock($optionProductType);
  683. $optionMock->expects($this->once())
  684. ->method('getValue')
  685. ->will($this->returnValue($optionProductTypeValue));
  686. $this->model->addOption($optionMock);
  687. $this->assertEquals($optionProductTypeValue, $this->model->getProductType());
  688. }
  689. public function testGetProductTypeWithProduct()
  690. {
  691. $productMock = $this->generateProductMock(
  692. self::PRODUCT_ID,
  693. self::PRODUCT_TYPE,
  694. self::PRODUCT_SKU,
  695. self::PRODUCT_NAME,
  696. self::PRODUCT_WEIGHT,
  697. self::PRODUCT_TAX_CLASS_ID,
  698. self::PRODUCT_COST
  699. );
  700. $this->model->setProduct($productMock);
  701. $this->assertEquals(self::PRODUCT_TYPE, $this->model->getProductType());
  702. }
  703. public function testSetOptions()
  704. {
  705. $optionCode1 = 1234;
  706. $optionMock1 = $this->createOptionMock($optionCode1);
  707. $optionCode2 = 7890;
  708. $optionMock2 = $this->createOptionMock($optionCode2);
  709. $this->assertSame($this->model, $this->model->setOptions([$optionMock1, $optionMock2]));
  710. $this->assertEquals([$optionMock1, $optionMock2], $this->model->getOptions());
  711. $this->assertEquals($optionMock1, $this->model->getOptionByCode($optionCode1));
  712. $this->assertEquals($optionMock2, $this->model->getOptionByCode($optionCode2));
  713. }
  714. public function testSetOptionsWithNull()
  715. {
  716. $this->assertEquals($this->model, $this->model->setOptions(null));
  717. }
  718. /**
  719. * @param $optionCode
  720. * @param array $optionData
  721. * @return \PHPUnit_Framework_MockObject_MockObject
  722. */
  723. private function createOptionMock($optionCode, $optionData = [])
  724. {
  725. $optionMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\Option::class)
  726. ->setMethods([
  727. 'setData',
  728. 'setItem',
  729. 'getItem',
  730. 'getCode',
  731. '__wakeup',
  732. 'isDeleted',
  733. 'delete',
  734. 'getValue',
  735. 'getProduct',
  736. 'save'
  737. ])
  738. ->disableOriginalConstructor()
  739. ->getMock();
  740. $optionMock->expects($this->any())
  741. ->method('setData')
  742. ->with($optionData)
  743. ->will($this->returnValue($optionMock));
  744. $optionMock->expects($this->any())
  745. ->method('setItem')
  746. ->with($this->model)
  747. ->will($this->returnValue($optionMock));
  748. $optionMock->expects($this->any())
  749. ->method('getCode')
  750. ->will($this->returnValue($optionCode));
  751. return $optionMock;
  752. }
  753. public function testAddOptionArray()
  754. {
  755. $optionCode = 1234;
  756. $optionData = ['product' => 'test', 'code' => $optionCode];
  757. $optionMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\Option::class)
  758. ->setMethods(['setData', 'setItem', 'getCode', '__wakeup', 'isDeleted'])
  759. ->disableOriginalConstructor()
  760. ->getMock();
  761. $optionMock->expects($this->once())
  762. ->method('setData')
  763. ->with($optionData)
  764. ->will($this->returnValue($optionMock));
  765. $optionMock->expects($this->once())
  766. ->method('setItem')
  767. ->with($this->model)
  768. ->will($this->returnValue($optionMock));
  769. $optionMock->expects($this->exactly(3))
  770. ->method('getCode')
  771. ->will($this->returnValue($optionCode));
  772. $this->itemOptionFactory->expects($this->at(0))
  773. ->method('create')
  774. ->will($this->returnValue($optionMock));
  775. $this->model->addOption($optionData);
  776. $this->assertEquals([$optionMock], $this->model->getOptions());
  777. $this->assertEquals([$optionCode => $optionMock], $this->model->getOptionsByCode());
  778. $this->assertEquals($optionMock, $this->model->getOptionByCode($optionCode));
  779. }
  780. public function testUpdateQtyOption()
  781. {
  782. $productMock = $this->generateProductMock(
  783. self::PRODUCT_ID,
  784. self::PRODUCT_TYPE,
  785. self::PRODUCT_SKU,
  786. self::PRODUCT_NAME,
  787. self::PRODUCT_WEIGHT,
  788. self::PRODUCT_TAX_CLASS_ID,
  789. self::PRODUCT_COST
  790. );
  791. $typeInstanceMock = $this->getMockForAbstractClass(
  792. \Magento\Catalog\Model\Product\Type\AbstractType::class,
  793. [],
  794. '',
  795. false,
  796. false,
  797. true,
  798. ['updateQtyOption']
  799. );
  800. $productMock->expects($this->once())
  801. ->method('getTypeInstance')
  802. ->will($this->returnValue($typeInstanceMock));
  803. $optionMock = $this->getMockBuilder(\Magento\Framework\DataObject::class)
  804. ->disableOriginalConstructor()
  805. ->setMethods(['getProduct'])
  806. ->getMock();
  807. $optionMock->expects($this->once())
  808. ->method('getProduct')
  809. ->will($this->returnValue($productMock));
  810. $quantityValue = 12;
  811. $this->model->setProduct($productMock);
  812. $typeInstanceMock->expects($this->once())
  813. ->method('updateQtyOption')
  814. ->with($this->model->getOptions(), $optionMock, $quantityValue, $productMock);
  815. $this->assertEquals($this->model, $this->model->updateQtyOption($optionMock, $quantityValue));
  816. }
  817. public function testRemoveOption()
  818. {
  819. $optionCode = 1234;
  820. $optionMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\Option::class)
  821. ->setMethods(['setItem', 'getCode', '__wakeup', 'isDeleted'])
  822. ->disableOriginalConstructor()
  823. ->getMock();
  824. $optionMock->expects($this->once())
  825. ->method('setItem')
  826. ->with($this->model)
  827. ->will($this->returnValue($optionMock));
  828. $optionMock->expects($this->exactly(3))
  829. ->method('getCode')
  830. ->will($this->returnValue($optionCode));
  831. $optionMock->expects($this->at(0))
  832. ->method('isDeleted')
  833. ->will($this->returnValue(false));
  834. $optionMock->expects($this->at(1))
  835. ->method('isDeleted')
  836. ->will($this->returnValue(true));
  837. $this->model->addOption($optionMock);
  838. $this->assertEquals($this->model, $this->model->removeOption($optionCode));
  839. }
  840. public function testRemoveOptionNoOptionCodeExists()
  841. {
  842. $this->assertEquals($this->model, $this->model->removeOption('random'));
  843. }
  844. public function testGetOptionByCodeNonExistent()
  845. {
  846. $this->assertNull($this->model->getOptionByCode('random'));
  847. }
  848. public function testGetOptionByCodeDeletedCode()
  849. {
  850. $optionCode = 1234;
  851. $optionMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\Option::class)
  852. ->setMethods(['setItem', 'getCode', '__wakeup', 'isDeleted'])
  853. ->disableOriginalConstructor()
  854. ->getMock();
  855. $optionMock->expects($this->once())
  856. ->method('setItem')
  857. ->with($this->model)
  858. ->will($this->returnValue($optionMock));
  859. $optionMock->expects($this->exactly(3))
  860. ->method('getCode')
  861. ->will($this->returnValue($optionCode));
  862. $optionMock->expects($this->once())
  863. ->method('isDeleted')
  864. ->will($this->returnValue(true));
  865. $this->model->addOption($optionMock);
  866. $this->assertNull($this->model->getOptionByCode($optionCode));
  867. }
  868. public function testGetOptionByCodeNotDeletedCode()
  869. {
  870. $optionCode = 1234;
  871. $optionMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\Option::class)
  872. ->setMethods(['setItem', 'getCode', '__wakeup', 'isDeleted'])
  873. ->disableOriginalConstructor()
  874. ->getMock();
  875. $optionMock->expects($this->once())
  876. ->method('setItem')
  877. ->with($this->model)
  878. ->will($this->returnValue($optionMock));
  879. $optionMock->expects($this->exactly(3))
  880. ->method('getCode')
  881. ->will($this->returnValue($optionCode));
  882. $optionMock->expects($this->once())
  883. ->method('isDeleted')
  884. ->will($this->returnValue(false));
  885. $this->model->addOption($optionMock);
  886. $this->assertSame($optionMock, $this->model->getOptionByCode($optionCode));
  887. }
  888. public function testGetBuyRequestNoOptionByCode()
  889. {
  890. $quantity = 12;
  891. $this->localeFormat->expects($this->at(0))
  892. ->method('getNumber')
  893. ->with($quantity)
  894. ->will($this->returnValue($quantity));
  895. $this->model->setQty($quantity);
  896. $this->assertEquals($quantity, $this->model->getQty());
  897. $buyRequest = $this->model->getBuyRequest();
  898. $this->assertEquals(0, $buyRequest->getOriginalQty());
  899. $this->assertEquals($quantity, $buyRequest->getQty());
  900. }
  901. public function testGetBuyRequestOptionByCode()
  902. {
  903. $optionCode = "info_buyRequest";
  904. $buyRequestQuantity = 23;
  905. $optionMock = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item\Option::class)
  906. ->setMethods(['setItem', 'getCode', '__wakeup', 'getValue'])
  907. ->disableOriginalConstructor()
  908. ->getMock();
  909. $optionMock->expects($this->once())
  910. ->method('setItem')
  911. ->with($this->model)
  912. ->will($this->returnValue($optionMock));
  913. $optionMock->expects($this->exactly(3))
  914. ->method('getCode')
  915. ->will($this->returnValue($optionCode));
  916. $optionMock->expects($this->any())
  917. ->method('getValue')
  918. ->will($this->returnValue('{"qty":23}'));
  919. $this->model->addOption($optionMock);
  920. $quantity = 12;
  921. $this->localeFormat->expects($this->at(0))
  922. ->method('getNumber')
  923. ->with($quantity)
  924. ->will($this->returnValue($quantity));
  925. $this->model->setQty($quantity);
  926. $this->assertEquals($quantity, $this->model->getQty());
  927. $this->serializer->expects($this->any())
  928. ->method('unserialize')
  929. ->willReturn(json_decode($optionMock->getValue(), true));
  930. $buyRequest = $this->model->getBuyRequest();
  931. $this->assertEquals($buyRequestQuantity, $buyRequest->getOriginalQty());
  932. $this->assertEquals($quantity, $buyRequest->getQty());
  933. }
  934. public function testSetHasErrorFalse()
  935. {
  936. $this->errorInfos->expects($this->once())
  937. ->method('clear');
  938. $this->assertEquals($this->model, $this->model->setHasError(false));
  939. $this->assertFalse($this->model->getHasError());
  940. }
  941. public function testSetHasErrorTrue()
  942. {
  943. $this->errorInfos->expects($this->once())
  944. ->method('addItem')
  945. ->with(null, null, null, null);
  946. $this->assertEquals($this->model, $this->model->setHasError(true));
  947. $this->assertTrue($this->model->getHasError());
  948. $this->assertEquals('', $this->model->getMessage());
  949. }
  950. public function testAddErrorInfo()
  951. {
  952. $origin = 'origin';
  953. $code = 1;
  954. $message = "message";
  955. $additionalData = new \Magento\Framework\DataObject();
  956. $additionalData->setTemp(true);
  957. $this->errorInfos->expects($this->once())
  958. ->method('addItem')
  959. ->with($origin, $code, $message, $additionalData);
  960. $this->assertEquals($this->model, $this->model->addErrorInfo($origin, $code, $message, $additionalData));
  961. $this->assertTrue($this->model->getHasError());
  962. $this->assertEquals($message, $this->model->getMessage());
  963. }
  964. public function testGetErrorInfos()
  965. {
  966. $retValue = 'return value';
  967. $this->errorInfos->expects($this->once())
  968. ->method('getItems')
  969. ->will($this->returnValue($retValue));
  970. $this->assertEquals($retValue, $this->model->getErrorInfos());
  971. }
  972. public function testRemoveErrorInfosByParams()
  973. {
  974. $message = "message";
  975. $message2 = "message2";
  976. $this->errorInfos->expects($this->at(0))
  977. ->method('addItem')
  978. ->with(null, null, $message);
  979. $this->errorInfos->expects($this->at(1))
  980. ->method('addItem')
  981. ->with(null, null, $message2);
  982. $this->assertEquals($this->model, $this->model->addErrorInfo(null, null, $message));
  983. $this->assertEquals($this->model, $this->model->addErrorInfo(null, null, $message2));
  984. $this->assertEquals($message . "\n" . $message2, $this->model->getMessage());
  985. $params = [];
  986. $removedItems = [['message' => $message]];
  987. $this->errorInfos->expects($this->once())
  988. ->method('removeItemsByParams')
  989. ->with($params)
  990. ->will($this->returnValue($removedItems));
  991. $this->errorInfos->expects($this->once())
  992. ->method('getItems')
  993. ->will($this->returnValue(true));
  994. $this->assertEquals($this->model, $this->model->removeErrorInfosByParams($params));
  995. $this->assertEquals($message2, $this->model->getMessage());
  996. }
  997. public function testRemoveErrorInfosByParamsAllErrorsRemoved()
  998. {
  999. $message = "message";
  1000. $message2 = "message2";
  1001. $this->errorInfos->expects($this->at(0))
  1002. ->method('addItem')
  1003. ->with(null, null, $message);
  1004. $this->errorInfos->expects($this->at(1))
  1005. ->method('addItem')
  1006. ->with(null, null, $message2);
  1007. $this->assertEquals($this->model, $this->model->addErrorInfo(null, null, $message));
  1008. $this->assertEquals($this->model, $this->model->addErrorInfo(null, null, $message2));
  1009. $this->assertEquals($message . "\n" . $message2, $this->model->getMessage());
  1010. $params = [];
  1011. $removedItems = [['message' => $message], ['message' => $message2]];
  1012. $this->errorInfos->expects($this->once())
  1013. ->method('removeItemsByParams')
  1014. ->with($params)
  1015. ->will($this->returnValue($removedItems));
  1016. $this->errorInfos->expects($this->once())
  1017. ->method('getItems')
  1018. ->will($this->returnValue([]));
  1019. $this->assertEquals($this->model, $this->model->removeErrorInfosByParams($params));
  1020. $this->assertFalse($this->model->getHasError());
  1021. $this->assertEquals('', $this->model->getMessage());
  1022. }
  1023. /**
  1024. * Test method \Magento\Quote\Model\Quote\Item::saveItemOptions
  1025. */
  1026. public function testSaveItemOptions()
  1027. {
  1028. $optionMockDeleted = $this->createOptionMock(100);
  1029. $optionMockDeleted->expects(self::once())->method('isDeleted')->willReturn(true);
  1030. $optionMockDeleted->expects(self::once())->method('delete');
  1031. $optionMock1 = $this->createOptionMock(200);
  1032. $optionMock1->expects(self::once())->method('isDeleted')->willReturn(false);
  1033. $quoteItemMock1 = $this->createPartialMock(\Magento\Quote\Model\Quote\Item::class, ['getId']);
  1034. $quoteItemMock1->expects(self::once())->method('getId')->willReturn(null);
  1035. $optionMock1->expects(self::exactly(2))->method('getItem')->willReturn($quoteItemMock1);
  1036. $optionMock1->expects(self::exactly(2))->method('setItem')->with($this->model);
  1037. $optionMock1->expects(self::once())->method('save');
  1038. $optionMock2 = $this->createOptionMock(300);
  1039. $optionMock2->expects(self::once())->method('isDeleted')->willReturn(false);
  1040. $quoteItemMock2 = $this->createPartialMock(\Magento\Quote\Model\Quote\Item::class, ['getId']);
  1041. $quoteItemMock2->expects(self::once())->method('getId')->willReturn(11);
  1042. $optionMock2->expects(self::exactly(2))->method('getItem')->willReturn($quoteItemMock2);
  1043. $optionMock2->expects(self::once())->method('setItem')->with($this->model);
  1044. $optionMock2->expects(self::once())->method('save');
  1045. $this->model->setOptions([$optionMockDeleted, $optionMock1, $optionMock2]);
  1046. $this->model->saveItemOptions();
  1047. }
  1048. }