2dc851478643522217e714070bcdaa4dfbc387b7
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Object / Container / ContainerTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Object\Container;
3
4 /***************************************************************
5 * Copyright notice
6 * (c) 2010 Daniel Pötzinger
7 * (c) 2010 Bastian Waidelich <bastian@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 require_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('extbase') . 'Tests/Unit/Object/Container/Fixtures/Testclasses.php';
27 require_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('extbase') . 'Tests/Unit/Object/Container/Fixtures/NamespaceTestclasses.php';
28
29 /**
30 * Testcase for class t3lib_object_Container.
31 *
32 * @author Daniel Pötzinger
33 * @author Bastian Waidelich <bastian@typo3.org>
34 */
35 class ContainerTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {
36
37 /**
38 * @var \TYPO3\CMS\Extbase\Object\Container\Container
39 */
40 private $container;
41
42 /**
43 * @var \TYPO3\CMS\Extbase\Object\Container\ClassInfo
44 */
45 private $cachedClassInfo;
46
47 public function setUp() {
48 //our mocked cache will allways indicate that he has nothing in the cache to force that we get the real classinfo
49 $mockedCache = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\Container\\ClassInfoCache', array('get'));
50 $mockedCache->expects($this->any())->method('get')->will($this->returnValue(FALSE));
51 $mockedCache->expects($this->never())->method('has');
52 $this->container = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\Container\\Container', array('log', 'getClassInfoCache'));
53 $this->container->expects($this->any())->method('getClassInfoCache')->will($this->returnValue($mockedCache));
54 }
55
56 /**
57 * @test
58 */
59 public function getInstanceReturnsInstanceOfSimpleClass() {
60 $object = $this->container->getInstance('t3lib_object_tests_c');
61 $this->assertInstanceOf('t3lib_object_tests_c', $object);
62 }
63
64 /**
65 * @test
66 */
67 public function getInstanceReturnsInstanceOfSimpleNamespacedClass() {
68 $object = $this->container->getInstance('TYPO3\\CMS\\Extbase\\Tests\\Unit\\Object\\Container\\Fixtures\\NamespacedClass');
69 $this->assertInstanceOf('TYPO3\\CMS\\Extbase\\Tests\\Unit\\Object\\Container\\Fixtures\\NamespacedClass', $object);
70 }
71
72 /**
73 * @test
74 */
75 public function getInstanceReturnsInstanceOfAClassWithConstructorInjection() {
76 $object = $this->container->getInstance('t3lib_object_tests_b');
77 $this->assertInstanceOf('t3lib_object_tests_b', $object);
78 $this->assertInstanceOf('t3lib_object_tests_c', $object->c);
79 }
80
81 /**
82 * @test
83 */
84 public function getInstanceReturnsInstanceOfAClassWithTwoLevelDependency() {
85 $object = $this->container->getInstance('t3lib_object_tests_a');
86 $this->assertInstanceOf('t3lib_object_tests_a', $object);
87 $this->assertInstanceOf('t3lib_object_tests_c', $object->b->c);
88 }
89
90 /**
91 * @test
92 */
93 public function getInstanceReturnsInstanceOfAClassWithMixedSimpleTypeAndConstructorInjection() {
94 $object = $this->container->getInstance('t3lib_object_tests_amixed_array');
95 $this->assertInstanceOf('t3lib_object_tests_amixed_array', $object);
96 $this->assertEquals(array('some' => 'default'), $object->myvalue);
97 }
98
99 /**
100 * @test
101 */
102 public function getInstanceReturnsInstanceOfAClassWithMixedSimpleTypeAndConstructorInjectionWithNullDefaultValue() {
103 $object = $this->container->getInstance('t3lib_object_tests_amixed_null');
104 $this->assertInstanceOf('t3lib_object_tests_amixed_null', $object);
105 $this->assertNull($object->myvalue);
106 }
107
108 /**
109 * @test
110 * @expectedException \TYPO3\CMS\Extbase\Object\Exception
111 */
112 public function getInstanceThrowsExceptionWhenTryingToInstanciateASingletonWithConstructorParameters() {
113 $this->container->getInstance('t3lib_object_tests_amixed_array_singleton', array('somevalue'));
114 }
115
116 /**
117 * @test
118 */
119 public function getInstanceReturnsInstanceOfAClassWithConstructorInjectionAndDefaultConstructorParameters() {
120 $object = $this->container->getInstance('t3lib_object_tests_amixed_array');
121 $this->assertInstanceOf('t3lib_object_tests_b', $object->b);
122 $this->assertInstanceOf('t3lib_object_tests_c', $object->c);
123 $this->assertEquals(array('some' => 'default'), $object->myvalue);
124 }
125
126 /**
127 * @test
128 */
129 public function getInstancePassesGivenParameterToTheNewObject() {
130 $mockObject = $this->getMock('t3lib_object_tests_c');
131 $object = $this->container->getInstance('t3lib_object_tests_a', array($mockObject));
132 $this->assertInstanceOf('t3lib_object_tests_a', $object);
133 $this->assertSame($mockObject, $object->c);
134 }
135
136 /**
137 * @test
138 */
139 public function getInstanceReturnsAFreshInstanceIfObjectIsNoSingleton() {
140 $object1 = $this->container->getInstance('t3lib_object_tests_a');
141 $object2 = $this->container->getInstance('t3lib_object_tests_a');
142 $this->assertNotSame($object1, $object2);
143 }
144
145 /**
146 * @test
147 */
148 public function getInstanceReturnsSameInstanceInstanceIfObjectIsSingleton() {
149 $object1 = $this->container->getInstance('t3lib_object_tests_singleton');
150 $object2 = $this->container->getInstance('t3lib_object_tests_singleton');
151 $this->assertSame($object1, $object2);
152 }
153
154 /**
155 * @test
156 * @expectedException \TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException
157 */
158 public function getInstanceThrowsExceptionIfPrototypeObjectsWiredViaConstructorInjectionContainCyclicDependencies() {
159 $this->container->getInstance('t3lib_object_tests_cyclic1WithSetterDependency');
160 }
161
162 /**
163 * @test
164 * @expectedException \TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException
165 */
166 public function getInstanceThrowsExceptionIfPrototypeObjectsWiredViaSetterInjectionContainCyclicDependencies() {
167 $this->container->getInstance('t3lib_object_tests_cyclic1');
168 }
169
170 /**
171 * @test
172 * @expectedException \TYPO3\CMS\Extbase\Object\Exception
173 */
174 public function getInstanceThrowsExceptionIfClassWasNotFound() {
175 $this->container->getInstance('nonextistingclass_bla');
176 }
177
178 /**
179 * @test
180 */
181 public function getInstanceUsesClassNameMd5AsCacheKey() {
182 $className = 'TYPO3\\CMS\\Extbase\\Tests\\Unit\\Object\\Container\\Fixtures\\NamespacedClass';
183 $classNameHash = md5($className);
184 $mockedCache = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\Container\\ClassInfoCache', array('has', 'set', 'get'));
185 $container = $this->getMock('TYPO3\\CMS\\Extbase\\Object\\Container\\Container', array('log', 'getClassInfoCache'));
186 $container->expects($this->any())->method('getClassInfoCache')->will($this->returnValue($mockedCache));
187 $mockedCache->expects($this->never())->method('has');
188 $mockedCache->expects($this->once())->method('get')->with($classNameHash)->will($this->returnValue(FALSE));
189 $mockedCache->expects($this->once())->method('set')->with($classNameHash, $this->anything())->will($this->returnCallback(array($this, 'setClassInfoCacheCallback')));
190 $container->getInstance($className);
191 $this->assertInstanceOf('TYPO3\\CMS\\Extbase\\Object\\Container\\ClassInfo', $this->cachedClassInfo);
192 $this->assertEquals($className, $this->cachedClassInfo->getClassName());
193 }
194
195 /**
196 * Callback for getInstanceUsesClassNameSha1AsCacheKey
197 *
198 * @param string $id
199 * @param \TYPO3\CMS\Extbase\Object\Container\ClassInfo $value
200 * @return void
201 */
202 public function setClassInfoCacheCallback($id, \TYPO3\CMS\Extbase\Object\Container\ClassInfo $value) {
203 $this->cachedClassInfo = $value;
204 }
205
206 /**
207 * @test
208 */
209 public function getEmptyObjectReturnsInstanceOfSimpleClass() {
210 $object = $this->container->getEmptyObject('t3lib_object_tests_c');
211 $this->assertInstanceOf('t3lib_object_tests_c', $object);
212 }
213
214 /**
215 * @test
216 */
217 public function test_canGetChildClass() {
218 $object = $this->container->getInstance('t3lib_object_tests_b_child');
219 $this->assertInstanceOf('t3lib_object_tests_b_child', $object);
220 }
221
222 /**
223 * @test
224 */
225 public function test_canInjectInterfaceInClass() {
226 $this->container->registerImplementation('t3lib_object_tests_someinterface', 't3lib_object_tests_someimplementation');
227 $object = $this->container->getInstance('t3lib_object_tests_needsinterface');
228 $this->assertInstanceOf('t3lib_object_tests_needsinterface', $object);
229 $this->assertInstanceOf('t3lib_object_tests_someinterface', $object->dependency);
230 $this->assertInstanceOf('t3lib_object_tests_someimplementation', $object->dependency);
231 }
232
233 /**
234 * @test
235 */
236 public function test_canBuildCyclicDependenciesOfSingletonsWithSetter() {
237 $object = $this->container->getInstance('t3lib_object_tests_resolveablecyclic1');
238 $this->assertInstanceOf('t3lib_object_tests_resolveablecyclic1', $object);
239 $this->assertInstanceOf('t3lib_object_tests_resolveablecyclic1', $object->o2->o3->o1);
240 }
241
242 /**
243 * @test
244 */
245 public function singletonWhichRequiresPrototypeViaSetterInjectionWorksAndAddsDebugMessage() {
246 $this->container->expects($this->once())->method('log')->with('The singleton "t3lib_object_singletonNeedsPrototype" needs a prototype in "injectDependency". This is often a bad code smell; often you rather want to inject a singleton.', 1);
247 $object = $this->container->getInstance('t3lib_object_singletonNeedsPrototype');
248 $this->assertInstanceOf('t3lib_object_prototype', $object->dependency);
249 }
250
251 /**
252 * @test
253 */
254 public function singletonWhichRequiresSingletonViaSetterInjectionWorks() {
255 $this->container->expects($this->never())->method('log');
256 $object = $this->container->getInstance('t3lib_object_singletonNeedsSingleton');
257 $this->assertInstanceOf('t3lib_object_singleton', $object->dependency);
258 }
259
260 /**
261 * @test
262 */
263 public function prototypeWhichRequiresPrototypeViaSetterInjectionWorks() {
264 $this->container->expects($this->never())->method('log');
265 $object = $this->container->getInstance('t3lib_object_prototypeNeedsPrototype');
266 $this->assertInstanceOf('t3lib_object_prototype', $object->dependency);
267 }
268
269 /**
270 * @test
271 */
272 public function prototypeWhichRequiresSingletonViaSetterInjectionWorks() {
273 $this->container->expects($this->never())->method('log');
274 $object = $this->container->getInstance('t3lib_object_prototypeNeedsSingleton');
275 $this->assertInstanceOf('t3lib_object_singleton', $object->dependency);
276 }
277
278 /**
279 * @test
280 */
281 public function singletonWhichRequiresPrototypeViaConstructorInjectionWorksAndAddsDebugMessage() {
282 $this->container->expects($this->once())->method('log')->with('The singleton "t3lib_object_singletonNeedsPrototypeInConstructor" needs a prototype in the constructor. This is often a bad code smell; often you rather want to inject a singleton.', 1);
283 $object = $this->container->getInstance('t3lib_object_singletonNeedsPrototypeInConstructor');
284 $this->assertInstanceOf('t3lib_object_prototype', $object->dependency);
285 }
286
287 /**
288 * @test
289 */
290 public function singletonWhichRequiresSingletonViaConstructorInjectionWorks() {
291 $this->container->expects($this->never())->method('log');
292 $object = $this->container->getInstance('t3lib_object_singletonNeedsSingletonInConstructor');
293 $this->assertInstanceOf('t3lib_object_singleton', $object->dependency);
294 }
295
296 /**
297 * @test
298 */
299 public function prototypeWhichRequiresPrototypeViaConstructorInjectionWorks() {
300 $this->container->expects($this->never())->method('log');
301 $object = $this->container->getInstance('t3lib_object_prototypeNeedsPrototypeInConstructor');
302 $this->assertInstanceOf('t3lib_object_prototype', $object->dependency);
303 }
304
305 /**
306 * @test
307 */
308 public function prototypeWhichRequiresSingletonViaConstructorInjectionWorks() {
309 $this->container->expects($this->never())->method('log');
310 $object = $this->container->getInstance('t3lib_object_prototypeNeedsSingletonInConstructor');
311 $this->assertInstanceOf('t3lib_object_singleton', $object->dependency);
312 }
313 }
314
315 ?>