AbstractEntityTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Eav\Test\Unit\Model\Entity;
  7. use Magento\Eav\Model\Entity\AbstractEntity;
  8. use Magento\Framework\DB\Adapter\AdapterInterface;
  9. use Magento\Framework\DB\Adapter\DuplicateException;
  10. use Magento\Framework\Model\AbstractModel;
  11. use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
  12. /**
  13. * Class AbstractEntityTest
  14. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  15. */
  16. class AbstractEntityTest extends \PHPUnit\Framework\TestCase
  17. {
  18. /**
  19. * Entity model to be tested
  20. * @var AbstractEntity|\PHPUnit_Framework_MockObject_MockObject
  21. */
  22. protected $_model;
  23. /** @var \Magento\Eav\Model\Config */
  24. protected $eavConfig;
  25. protected function setUp()
  26. {
  27. $objectManager = new ObjectManager($this);
  28. $this->eavConfig = $this->createMock(\Magento\Eav\Model\Config::class);
  29. $arguments = $objectManager->getConstructArguments(
  30. AbstractEntity::class,
  31. ['eavConfig' => $this->eavConfig]
  32. );
  33. $this->_model = $this->getMockForAbstractClass(
  34. AbstractEntity::class,
  35. $arguments
  36. );
  37. }
  38. protected function tearDown()
  39. {
  40. $this->_model = null;
  41. }
  42. /**
  43. * @param array $attribute1Sort
  44. * @param array $attribute2Sort
  45. * @param float $expected
  46. *
  47. * @dataProvider compareAttributesDataProvider
  48. */
  49. public function testCompareAttributes($attribute1Sort, $attribute2Sort, $expected)
  50. {
  51. $attribute1 = $this->createPartialMock(\Magento\Eav\Model\Entity\Attribute::class, ['__wakeup']);
  52. $attribute1->setAttributeSetInfo([0 => $attribute1Sort]);
  53. $attribute2 = $this->createPartialMock(\Magento\Eav\Model\Entity\Attribute::class, ['__wakeup']);
  54. $attribute2->setAttributeSetInfo([0 => $attribute2Sort]);
  55. $this->assertEquals($expected, $this->_model->attributesCompare($attribute1, $attribute2));
  56. }
  57. /**
  58. * @return array
  59. */
  60. public static function compareAttributesDataProvider()
  61. {
  62. return [
  63. 'attribute1 bigger than attribute2' => [
  64. 'attribute1Sort' => ['group_sort' => 7, 'sort' => 5],
  65. 'attribute2Sort' => ['group_sort' => 5, 'sort' => 10],
  66. 'expected' => 1,
  67. ],
  68. 'attribute1 smaller than attribute2' => [
  69. 'attribute1Sort' => ['group_sort' => 7, 'sort' => 5],
  70. 'attribute2Sort' => ['group_sort' => 7, 'sort' => 10],
  71. 'expected' => -1,
  72. ],
  73. 'attribute1 equals to attribute2' => [
  74. 'attribute1Sort' => ['group_sort' => 7, 'sort' => 5],
  75. 'attribute2Sort' => ['group_sort' => 7, 'sort' => 5],
  76. 'expected' => 0,
  77. ]
  78. ];
  79. }
  80. /**
  81. * Get attribute list
  82. *
  83. * @return array
  84. */
  85. protected function _getAttributes()
  86. {
  87. $attributes = [];
  88. $codes = ['entity_type_id', 'attribute_set_id', 'created_at', 'updated_at', 'parent_id', 'increment_id'];
  89. foreach ($codes as $code) {
  90. $mock = $this->createPartialMock(
  91. \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class,
  92. ['getBackend', 'getBackendTable', '__wakeup']
  93. );
  94. $mock->setAttributeId($code);
  95. /** @var $backendModel \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend */
  96. $backendModel = $this->createPartialMock(
  97. \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend::class,
  98. ['getBackend', 'getBackendTable']
  99. );
  100. $backendModel->setAttribute($mock);
  101. $mock->expects($this->any())->method('getBackend')->will($this->returnValue($backendModel));
  102. $mock->expects($this->any())->method('getBackendTable')->will($this->returnValue($code . '_table'));
  103. $attributes[$code] = $mock;
  104. }
  105. return $attributes;
  106. }
  107. /**
  108. * Get adapter mock
  109. *
  110. * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\DB\Adapter\Pdo\Mysql
  111. */
  112. protected function _getConnectionMock()
  113. {
  114. $connection = $this->createPartialMock(\Magento\Framework\DB\Adapter\Pdo\Mysql::class, [
  115. 'describeTable',
  116. 'getIndexList',
  117. 'lastInsertId',
  118. 'insert',
  119. 'prepareColumnValue',
  120. 'select',
  121. 'query',
  122. 'delete'
  123. ]);
  124. $statement = $this->createPartialMock(
  125. \Zend_Db_Statement::class,
  126. ['closeCursor', 'columnCount', 'errorCode', 'errorInfo', 'fetch', 'nextRowset', 'rowCount']
  127. );
  128. $select = $this->createMock(\Magento\Framework\DB\Select::class);
  129. $select->expects($this->any())
  130. ->method('from')
  131. ->willReturnSelf();
  132. $connection->expects($this->any())->method('query')->will($this->returnValue($statement));
  133. $connection->expects(
  134. $this->any()
  135. )->method(
  136. 'describeTable'
  137. )->will(
  138. $this->returnValue(['value' => ['test']])
  139. );
  140. $connection->expects($this->any())->method('prepareColumnValue')->will($this->returnArgument(2));
  141. $connection->expects(
  142. $this->once()
  143. )->method(
  144. 'delete'
  145. )->with(
  146. $this->equalTo('test_table')
  147. )->will(
  148. $this->returnValue(true)
  149. );
  150. $connection->expects($this->any())
  151. ->method('select')
  152. ->willReturn($select);
  153. $connection->expects($this->any())
  154. ->method('getIndexList')
  155. ->willReturn(
  156. [
  157. 'PK_ENTITYTABLE' => [
  158. 'COLUMNS_LIST' => [
  159. 'entity_id'
  160. ]
  161. ]
  162. ]
  163. );
  164. return $connection;
  165. }
  166. /**
  167. * Get attribute mock
  168. *
  169. * @param string $attributeCode
  170. * @param int $attributeSetId
  171. * @return \PHPUnit_Framework_MockObject_MockObject|\Magento\Eav\Model\Entity\Attribute\AbstractAttribute
  172. */
  173. protected function _getAttributeMock($attributeCode, $attributeSetId)
  174. {
  175. $attribute = $this->createPartialMock(
  176. \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class,
  177. ['getBackend', 'getBackendTable', 'isInSet', 'getApplyTo', 'getAttributeCode', '__wakeup']
  178. );
  179. $attribute->setAttributeId($attributeCode);
  180. $attribute->expects(
  181. $this->any()
  182. )->method(
  183. 'getBackendTable'
  184. )->will(
  185. $this->returnValue($attributeCode . '_table')
  186. );
  187. $attribute->expects(
  188. $this->any()
  189. )->method(
  190. 'isInSet'
  191. )->with(
  192. $this->equalTo($attributeSetId)
  193. )->will(
  194. $this->returnValue(false)
  195. );
  196. $attribute->expects($this->any())->method('getAttributeCode')->will($this->returnValue($attributeCode));
  197. return $attribute;
  198. }
  199. /**
  200. * @param string $attributeCode
  201. * @param int $attributeSetId
  202. * @param array $productData
  203. * @param array $productOrigData
  204. *
  205. * @dataProvider productAttributesDataProvider
  206. */
  207. public function testSave($attributeCode, $attributeSetId, $productData, $productOrigData)
  208. {
  209. $object = $this->createPartialMock(
  210. \Magento\Catalog\Model\Product::class,
  211. ['getOrigData', '__wakeup', 'beforeSave', 'afterSave', 'validateBeforeSave']
  212. );
  213. $object->setEntityTypeId(1);
  214. foreach ($productData as $key => $value) {
  215. $object->setData($key, $value);
  216. }
  217. $object->expects($this->any())->method('getOrigData')->will($this->returnValue($productOrigData));
  218. $entityType = new \Magento\Framework\DataObject();
  219. $entityType->setEntityTypeCode('test');
  220. $entityType->setEntityTypeId(0);
  221. $entityType->setEntityTable('table');
  222. $attributes = $this->_getAttributes();
  223. $attribute = $this->_getAttributeMock($attributeCode, $attributeSetId);
  224. /** @var $backendModel \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend */
  225. $backendModel = $this->createPartialMock(
  226. \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend::class,
  227. [
  228. 'getBackend',
  229. 'getBackendTable',
  230. 'getAffectedFields',
  231. 'isStatic',
  232. 'getEntityValueId',
  233. ]
  234. );
  235. $backendModel->expects(
  236. $this->once()
  237. )->method(
  238. 'getAffectedFields'
  239. )->will(
  240. $this->returnValue(['test_table' => [['value_id' => 0, 'attribute_id' => $attributeCode]]])
  241. );
  242. $backendModel->expects($this->any())->method('isStatic')->will($this->returnValue(false));
  243. $backendModel->expects($this->never())->method('getEntityValueId');
  244. $backendModel->setAttribute($attribute);
  245. $attribute->expects($this->any())->method('getBackend')->will($this->returnValue($backendModel));
  246. $attribute->setId(222);
  247. $attributes[$attributeCode] = $attribute;
  248. $eavConfig = $this->getMockBuilder(\Magento\Eav\Model\Config::class)
  249. ->disableOriginalConstructor()
  250. ->getMock();
  251. $objectManager = new ObjectManager($this);
  252. $this->eavConfig = $this->createMock(\Magento\Eav\Model\Config::class);
  253. $arguments = $objectManager->getConstructArguments(
  254. AbstractEntity::class,
  255. [
  256. 'eavConfig' => $eavConfig,
  257. 'data' => [
  258. 'type' => $entityType,
  259. 'entityTable' => 'entityTable',
  260. 'attributesByCode' => $attributes
  261. ]
  262. ]
  263. );
  264. /** @var $model AbstractEntity|\PHPUnit_Framework_MockObject_MockObject */
  265. $model = $this->getMockBuilder(AbstractEntity::class)
  266. ->setConstructorArgs($arguments)
  267. ->setMethods(['_getValue', 'beginTransaction', 'commit', 'rollback', 'getConnection'])
  268. ->getMock();
  269. $model->expects($this->any())->method('_getValue')->will($this->returnValue($eavConfig));
  270. $model->expects($this->any())->method('getConnection')->will($this->returnValue($this->_getConnectionMock()));
  271. $eavConfig->expects($this->any())->method('getAttribute')->will(
  272. $this->returnCallback(
  273. function ($entityType, $attributeCode) use ($attributes) {
  274. return $entityType && isset($attributes[$attributeCode]) ? $attributes[$attributeCode] : null;
  275. }
  276. )
  277. );
  278. $model->isPartialSave(true);
  279. $model->save($object);
  280. }
  281. /**
  282. * @return array
  283. */
  284. public function productAttributesDataProvider()
  285. {
  286. $attributeSetId = 10;
  287. return [
  288. [
  289. 'test_attr',
  290. $attributeSetId,
  291. [
  292. 'test_attr' => 'test_attr',
  293. 'attribute_set_id' => $attributeSetId,
  294. 'entity_id' => null,
  295. 'store_id' => 1
  296. ],
  297. null,
  298. ],
  299. [
  300. 'test_attr',
  301. $attributeSetId,
  302. [
  303. 'test_attr' => 'test_attr',
  304. 'attribute_set_id' => $attributeSetId,
  305. 'entity_id' => 12345,
  306. 'store_id' => 1
  307. ],
  308. ['test_attr' => 'test_attr']
  309. ],
  310. [
  311. 'test_attr',
  312. $attributeSetId,
  313. ['test_attr' => '99.99', 'attribute_set_id' => $attributeSetId, 'entity_id' => 12345, 'store_id' => 1],
  314. ['test_attr' => '99.9900']
  315. ]
  316. ];
  317. }
  318. /**
  319. * @expectedException \Magento\Framework\Exception\AlreadyExistsException
  320. */
  321. public function testDuplicateExceptionProcessingOnSave()
  322. {
  323. $connection = $this->createMock(AdapterInterface::class);
  324. $connection->expects($this->once())->method('rollback');
  325. /** @var AbstractEntity|\PHPUnit_Framework_MockObject_MockObject $model */
  326. $model = $this->getMockBuilder(AbstractEntity::class)
  327. ->disableOriginalConstructor()
  328. ->setMethods(['getConnection'])
  329. ->getMockForAbstractClass();
  330. $model->expects($this->any())->method('getConnection')->willReturn($connection);
  331. /** @var AbstractModel|\PHPUnit_Framework_MockObject_MockObject $object */
  332. $object = $this->getMockBuilder(AbstractModel::class)
  333. ->disableOriginalConstructor()
  334. ->getMock();
  335. $object->expects($this->once())->method('hasDataChanges')->willReturn(true);
  336. $object->expects($this->once())->method('beforeSave')->willThrowException(new DuplicateException());
  337. $object->expects($this->once())->method('setHasDataChanges')->with(true);
  338. $model->save($object);
  339. }
  340. }