BehaviorRegistryTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\ORM;
  16. use Cake\Core\Configure;
  17. use Cake\Core\Plugin;
  18. use Cake\ORM\BehaviorRegistry;
  19. use Cake\ORM\Table;
  20. use Cake\TestSuite\TestCase;
  21. /**
  22. * Test case for BehaviorRegistry.
  23. */
  24. class BehaviorRegistryTest extends TestCase
  25. {
  26. /**
  27. * setup method.
  28. *
  29. * @return void
  30. */
  31. public function setUp()
  32. {
  33. parent::setUp();
  34. $this->Table = new Table(['table' => 'articles']);
  35. $this->EventManager = $this->Table->eventManager();
  36. $this->Behaviors = new BehaviorRegistry($this->Table);
  37. Configure::write('App.namespace', 'TestApp');
  38. }
  39. /**
  40. * tearDown
  41. *
  42. * @return void
  43. */
  44. public function tearDown()
  45. {
  46. Plugin::unload();
  47. unset($this->Table, $this->EventManager, $this->Behaviors);
  48. parent::tearDown();
  49. }
  50. /**
  51. * Test loading behaviors.
  52. *
  53. * @return void
  54. */
  55. public function testLoad()
  56. {
  57. Plugin::load('TestPlugin');
  58. $config = ['alias' => 'Sluggable', 'replacement' => '-'];
  59. $result = $this->Behaviors->load('Sluggable', $config);
  60. $this->assertInstanceOf('TestApp\Model\Behavior\SluggableBehavior', $result);
  61. $this->assertEquals($config, $result->config());
  62. $result = $this->Behaviors->load('TestPlugin.PersisterOne');
  63. $this->assertInstanceOf('TestPlugin\Model\Behavior\PersisterOneBehavior', $result);
  64. }
  65. /**
  66. * Test load() binding listeners.
  67. *
  68. * @return void
  69. */
  70. public function testLoadBindEvents()
  71. {
  72. $result = $this->EventManager->listeners('Model.beforeFind');
  73. $this->assertCount(0, $result);
  74. $this->Behaviors->load('Sluggable');
  75. $result = $this->EventManager->listeners('Model.beforeFind');
  76. $this->assertCount(1, $result);
  77. $this->assertInstanceOf('TestApp\Model\Behavior\SluggableBehavior', $result[0]['callable'][0]);
  78. $this->assertEquals('beforeFind', $result[0]['callable'][1], 'Method name should match.');
  79. }
  80. /**
  81. * Test load() with enabled = false
  82. *
  83. * @return void
  84. */
  85. public function testLoadEnabledFalse()
  86. {
  87. $result = $this->EventManager->listeners('Model.beforeFind');
  88. $this->assertCount(0, $result);
  89. $this->Behaviors->load('Sluggable', ['enabled' => false]);
  90. $result = $this->EventManager->listeners('Model.beforeFind');
  91. $this->assertCount(0, $result);
  92. }
  93. /**
  94. * Test loading plugin behaviors
  95. *
  96. * @return void
  97. */
  98. public function testLoadPlugin()
  99. {
  100. Plugin::load('TestPlugin');
  101. $result = $this->Behaviors->load('TestPlugin.PersisterOne');
  102. $expected = 'TestPlugin\Model\Behavior\PersisterOneBehavior';
  103. $this->assertInstanceOf($expected, $result);
  104. $this->assertInstanceOf($expected, $this->Behaviors->PersisterOne);
  105. $this->Behaviors->unload('PersisterOne');
  106. $result = $this->Behaviors->load('TestPlugin.PersisterOne', ['foo' => 'bar']);
  107. $this->assertInstanceOf($expected, $result);
  108. $this->assertInstanceOf($expected, $this->Behaviors->PersisterOne);
  109. }
  110. /**
  111. * Test load() on undefined class
  112. *
  113. * @expectedException \Cake\ORM\Exception\MissingBehaviorException
  114. * @return void
  115. */
  116. public function testLoadMissingClass()
  117. {
  118. $this->Behaviors->load('DoesNotExist');
  119. }
  120. /**
  121. * Test load() duplicate method error
  122. *
  123. * @expectedException \LogicException
  124. * @expectedExceptionMessage TestApp\Model\Behavior\DuplicateBehavior contains duplicate method "slugify"
  125. * @return void
  126. */
  127. public function testLoadDuplicateMethodError()
  128. {
  129. $this->Behaviors->load('Sluggable');
  130. $this->Behaviors->load('Duplicate');
  131. }
  132. /**
  133. * Test load() duplicate method aliasing
  134. *
  135. * @return void
  136. */
  137. public function testLoadDuplicateMethodAliasing()
  138. {
  139. $this->Behaviors->load('Tree');
  140. $this->Behaviors->load('Duplicate', [
  141. 'implementedFinders' => [
  142. 'renamed' => 'findChildren',
  143. ],
  144. 'implementedMethods' => [
  145. 'renamed' => 'slugify',
  146. ]
  147. ]);
  148. $this->assertTrue($this->Behaviors->hasMethod('renamed'));
  149. }
  150. /**
  151. * Test load() duplicate finder error
  152. *
  153. * @expectedException \LogicException
  154. * @expectedExceptionMessage TestApp\Model\Behavior\DuplicateBehavior contains duplicate finder "children"
  155. * @return void
  156. */
  157. public function testLoadDuplicateFinderError()
  158. {
  159. $this->Behaviors->load('Tree');
  160. $this->Behaviors->load('Duplicate');
  161. }
  162. /**
  163. * Test load() duplicate finder aliasing
  164. *
  165. * @return void
  166. */
  167. public function testLoadDuplicateFinderAliasing()
  168. {
  169. $this->Behaviors->load('Tree');
  170. $this->Behaviors->load('Duplicate', [
  171. 'implementedFinders' => [
  172. 'renamed' => 'findChildren',
  173. ]
  174. ]);
  175. $this->assertTrue($this->Behaviors->hasFinder('renamed'));
  176. }
  177. /**
  178. * test hasMethod()
  179. *
  180. * @return void
  181. */
  182. public function testHasMethod()
  183. {
  184. Plugin::load('TestPlugin');
  185. $this->Behaviors->load('TestPlugin.PersisterOne');
  186. $this->Behaviors->load('Sluggable');
  187. $this->assertTrue($this->Behaviors->hasMethod('slugify'));
  188. $this->assertTrue($this->Behaviors->hasMethod('SLUGIFY'));
  189. $this->assertTrue($this->Behaviors->hasMethod('persist'));
  190. $this->assertTrue($this->Behaviors->hasMethod('PERSIST'));
  191. $this->assertFalse($this->Behaviors->hasMethod('__construct'));
  192. $this->assertFalse($this->Behaviors->hasMethod('config'));
  193. $this->assertFalse($this->Behaviors->hasMethod('implementedEvents'));
  194. $this->assertFalse($this->Behaviors->hasMethod('nope'));
  195. $this->assertFalse($this->Behaviors->hasMethod('beforeFind'));
  196. $this->assertFalse($this->Behaviors->hasMethod('noSlug'));
  197. }
  198. /**
  199. * Test hasFinder() method.
  200. *
  201. * @return void
  202. */
  203. public function testHasFinder()
  204. {
  205. $this->Behaviors->load('Sluggable');
  206. $this->assertTrue($this->Behaviors->hasFinder('noSlug'));
  207. $this->assertTrue($this->Behaviors->hasFinder('noslug'));
  208. $this->assertTrue($this->Behaviors->hasFinder('NOSLUG'));
  209. $this->assertFalse($this->Behaviors->hasFinder('slugify'));
  210. $this->assertFalse($this->Behaviors->hasFinder('beforeFind'));
  211. $this->assertFalse($this->Behaviors->hasFinder('nope'));
  212. }
  213. /**
  214. * test call
  215. *
  216. * Setup a behavior, then replace it with a mock to verify methods are called.
  217. * use dummy return values to verify the return value makes it back
  218. *
  219. * @return void
  220. */
  221. public function testCall()
  222. {
  223. $this->Behaviors->load('Sluggable');
  224. $mockedBehavior = $this->getMockBuilder('Cake\ORM\Behavior')
  225. ->setMethods(['slugify'])
  226. ->disableOriginalConstructor()
  227. ->getMock();
  228. $this->Behaviors->set('Sluggable', $mockedBehavior);
  229. $mockedBehavior
  230. ->expects($this->once())
  231. ->method('slugify')
  232. ->with(['some value'])
  233. ->will($this->returnValue('some-thing'));
  234. $return = $this->Behaviors->call('slugify', [['some value']]);
  235. $this->assertSame('some-thing', $return);
  236. }
  237. /**
  238. * Test errors on unknown methods.
  239. *
  240. * @expectedException \BadMethodCallException
  241. * @expectedExceptionMessage Cannot call "nope"
  242. */
  243. public function testCallError()
  244. {
  245. $this->Behaviors->load('Sluggable');
  246. $this->Behaviors->call('nope');
  247. }
  248. /**
  249. * test call finder
  250. *
  251. * Setup a behavior, then replace it with a mock to verify methods are called.
  252. * use dummy return values to verify the return value makes it back
  253. *
  254. * @return void
  255. */
  256. public function testCallFinder()
  257. {
  258. $this->Behaviors->load('Sluggable');
  259. $mockedBehavior = $this->getMockBuilder('Cake\ORM\Behavior')
  260. ->setMethods(['findNoSlug'])
  261. ->disableOriginalConstructor()
  262. ->getMock();
  263. $this->Behaviors->set('Sluggable', $mockedBehavior);
  264. $query = $this->getMock('Cake\ORM\Query', [], [null, null]);
  265. $mockedBehavior
  266. ->expects($this->once())
  267. ->method('findNoSlug')
  268. ->with($query, [])
  269. ->will($this->returnValue('example'));
  270. $return = $this->Behaviors->callFinder('noSlug', [$query, []]);
  271. $this->assertSame('example', $return);
  272. }
  273. /**
  274. * Test errors on unknown methods.
  275. *
  276. * @expectedException \BadMethodCallException
  277. * @expectedExceptionMessage Cannot call finder "nope"
  278. */
  279. public function testCallFinderError()
  280. {
  281. $this->Behaviors->load('Sluggable');
  282. $this->Behaviors->callFinder('nope');
  283. }
  284. /**
  285. * Test errors on unloaded behavior methods.
  286. *
  287. * @expectedException \BadMethodCallException
  288. * @expectedExceptionMessage Cannot call "slugify" it does not belong to any attached behavior.
  289. */
  290. public function testUnloadBehaviorThenCall()
  291. {
  292. $this->Behaviors->load('Sluggable');
  293. $this->Behaviors->unload('Sluggable');
  294. $this->Behaviors->call('slugify');
  295. }
  296. /**
  297. * Test errors on unloaded behavior finders.
  298. *
  299. * @expectedException \BadMethodCallException
  300. * @expectedExceptionMessage Cannot call finder "noslug" it does not belong to any attached behavior.
  301. */
  302. public function testUnloadBehaviorThenCallFinder()
  303. {
  304. $this->Behaviors->load('Sluggable');
  305. $this->Behaviors->unload('Sluggable');
  306. $this->Behaviors->callFinder('noSlug');
  307. }
  308. /**
  309. * Test that unloading then reloading a behavior does not throw any errors.
  310. *
  311. * @return void
  312. */
  313. public function testUnloadBehaviorThenReload()
  314. {
  315. $this->Behaviors->load('Sluggable');
  316. $this->Behaviors->unload('Sluggable');
  317. $this->assertEmpty($this->Behaviors->loaded());
  318. $this->Behaviors->load('Sluggable');
  319. $this->assertEquals(['Sluggable'], $this->Behaviors->loaded());
  320. }
  321. /**
  322. * Test setTable() method.
  323. *
  324. * @return void
  325. */
  326. public function testSetTable()
  327. {
  328. $table = $this->getMock('Cake\ORM\Table');
  329. $table->expects($this->once())->method('eventManager');
  330. $this->Behaviors->setTable($table);
  331. }
  332. }