[TASK] Replace JavaScriptEncoder with json_encode()
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / BaseTestCase.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2005-2013 Robert Lemke (robert@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
27 /**
28 * The mother of all test cases.
29 *
30 * Don't sub class this test case but rather choose a more specialized base test case,
31 * such as UnitTestCase or FunctionalTestCase
32 *
33 */
34 abstract class BaseTestCase extends \PHPUnit_Framework_TestCase {
35
36 /**
37 * Whether global variables should be backed up
38 *
39 * @var boolean
40 */
41 protected $backupGlobals = TRUE;
42
43 /**
44 * Whether static attributes should be backed up
45 *
46 * @var boolean
47 */
48 protected $backupStaticAttributes = FALSE;
49
50 /**
51 * Creates a mock object which allows for calling protected methods and access of protected properties.
52 *
53 * @param string $originalClassName name of class to create the mock object of, must not be empty
54 * @param array<string> $methods name of the methods to mock
55 * @param array $arguments arguments to pass to constructor
56 * @param string $mockClassName the class name to use for the mock class
57 * @param boolean $callOriginalConstructor whether to call the constructor
58 * @param boolean $callOriginalClone whether to call the __clone method
59 * @param boolean $callAutoload whether to call any autoload function
60 *
61 * @return \PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface
62 * a mock of $originalClassName with access methods added
63 *
64 * @throws \InvalidArgumentException
65 *
66 * @see \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase::getAccessibleMock
67 */
68 protected function getAccessibleMock(
69 $originalClassName, array $methods = array(), array $arguments = array(), $mockClassName = '',
70 $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE
71 ) {
72 if ($originalClassName === '') {
73 throw new \InvalidArgumentException('$originalClassName must not be empty.', 1334701880);
74 }
75
76 return $this->getMock(
77 $this->buildAccessibleProxy($originalClassName),
78 $methods,
79 $arguments,
80 $mockClassName,
81 $callOriginalConstructor,
82 $callOriginalClone,
83 $callAutoload
84 );
85 }
86
87 /**
88 * Creates a proxy class of the specified class which allows
89 * for calling even protected methods and access of protected properties.
90 *
91 * @param string $className Name of class to make available, must not be empty
92 *
93 * @return string Fully qualified name of the built class, will not be empty
94 *
95 * @see Tx_Extbase_Tests_Unit_BaseTestCase::buildAccessibleProxy
96 */
97 protected function buildAccessibleProxy($className) {
98 $accessibleClassName = uniqid('Tx_Phpunit_AccessibleProxy');
99 $class = new \ReflectionClass($className);
100 $abstractModifier = $class->isAbstract() ? 'abstract ' : '';
101
102 eval(
103 $abstractModifier . 'class ' . $accessibleClassName .
104 ' extends ' . $className . ' implements \TYPO3\CMS\Core\Tests\AccessibleObjectInterface {' .
105 'public function _call($methodName) {' .
106 'if ($methodName === \'\') {' .
107 'throw new \InvalidArgumentException(\'$methodName must not be empty.\', 1334663993);' .
108 '}' .
109 '$args = func_get_args();' .
110 'return call_user_func_array(array($this, $methodName), array_slice($args, 1));' .
111 '}' .
112 'public function _callRef(' .
113 '$methodName, &$arg1 = NULL, &$arg2 = NULL, &$arg3 = NULL, &$arg4 = NULL, &$arg5= NULL, &$arg6 = NULL, ' .
114 '&$arg7 = NULL, &$arg8 = NULL, &$arg9 = NULL' .
115 ') {' .
116 'if ($methodName === \'\') {' .
117 'throw new \InvalidArgumentException(\'$methodName must not be empty.\', 1334664210);' .
118 '}' .
119 'switch (func_num_args()) {' .
120 'case 0:' .
121 'throw new RuntimeException(\'The case of 0 arguments is not supposed to happen.\', 1334703124);' .
122 'break;' .
123 'case 1:' .
124 '$returnValue = $this->$methodName();' .
125 'break;' .
126 'case 2:' .
127 '$returnValue = $this->$methodName($arg1);' .
128 'break;' .
129 'case 3:' .
130 '$returnValue = $this->$methodName($arg1, $arg2);' .
131 'break;' .
132 'case 4:' .
133 '$returnValue = $this->$methodName($arg1, $arg2, $arg3);' .
134 'break;' .
135 'case 5:' .
136 '$returnValue = $this->$methodName($arg1, $arg2, $arg3, $arg4);' .
137 'break;' .
138 'case 6:' .
139 '$returnValue = $this->$methodName($arg1, $arg2, $arg3, $arg4, $arg5);' .
140 'break;' .
141 'case 7:' .
142 '$returnValue = $this->$methodName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6);' .
143 'break;' .
144 'case 8:' .
145 '$returnValue = $this->$methodName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7);' .
146 'break;' .
147 'case 9:' .
148 '$returnValue = $this->$methodName($arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8);' .
149 'break;' .
150 'case 10:' .
151 '$returnValue = $this->$methodName(' .
152 '$arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9' .
153 ');' .
154 'break;' .
155 'default:' .
156 'throw new \InvalidArgumentException(' .
157 '\'_callRef currently only allows calls to methods with no more than 9 parameters.\'' .
158 ');' .
159 '}' .
160 'return $returnValue;' .
161 '}' .
162 'public function _set($propertyName, $value) {' .
163 'if ($propertyName === \'\') {' .
164 'throw new \InvalidArgumentException(\'$propertyName must not be empty.\', 1334664355);' .
165 '}' .
166 '$this->$propertyName = $value;' .
167 '}' .
168 'public function _setRef($propertyName, &$value) {' .
169 'if ($propertyName === \'\') {' .
170 'throw new \InvalidArgumentException(\'$propertyName must not be empty.\', 1334664545);' .
171 '}' .
172 '$this->$propertyName = $value;' .
173 '}' .
174 'public function _setStatic($propertyName, $value) {' .
175 'if ($propertyName === \'\') {' .
176 'throw new \InvalidArgumentException(\'$propertyName must not be empty.\', 1344242602);' .
177 '}' .
178 'self::$$propertyName = $value;' .
179 '}' .
180 'public function _get($propertyName) {' .
181 'if ($propertyName === \'\') {' .
182 'throw new \InvalidArgumentException(\'$propertyName must not be empty.\', 1334664967);' .
183 '}' .
184 'return $this->$propertyName;' .
185 '}' .
186 'public function _getStatic($propertyName) {' .
187 'if ($propertyName === \'\') {' .
188 'throw new \InvalidArgumentException(\'$propertyName must not be empty.\', 1344242603);' .
189 '}' .
190 'return self::$$propertyName;' .
191 '}' .
192 '}'
193 );
194
195 return $accessibleClassName;
196 }
197
198 /**
199 * Helper function to call protected or private methods
200 *
201 * @param object $object The object to be invoked
202 * @param string $name the name of the method to call
203 * @return mixed
204 */
205 protected function callInaccessibleMethod($object, $name) {
206 // Remove first two arguments ($object and $name)
207 $arguments = func_get_args();
208 array_splice($arguments, 0, 2);
209
210 $reflectionObject = new \ReflectionObject($object);
211 $reflectionMethod = $reflectionObject->getMethod($name);
212 $reflectionMethod->setAccessible(TRUE);
213 return $reflectionMethod->invokeArgs($object, $arguments);
214 }
215
216 /**
217 * Injects $dependency into property $name of $target
218 *
219 * This is a convenience method for setting a protected or private property in
220 * a test subject for the purpose of injecting a dependency.
221 *
222 * @param object $target The instance which needs the dependency
223 * @param string $name Name of the property to be injected
224 * @param object $dependency The dependency to inject – usually an object but can also be any other type
225 * @return void
226 * @throws \RuntimeException
227 * @throws \InvalidArgumentException
228 */
229 protected function inject($target, $name, $dependency) {
230 if (!is_object($target)) {
231 throw new \InvalidArgumentException('Wrong type for argument $target, must be object.');
232 }
233
234 $objectReflection = new \ReflectionObject($target);
235 $methodNamePart = strtoupper($name[0]) . substr($name, 1);
236 if ($objectReflection->hasMethod('set' . $methodNamePart)) {
237 $methodName = 'set' . $methodNamePart;
238 $target->$methodName($dependency);
239 } elseif ($objectReflection->hasMethod('inject' . $methodNamePart)) {
240 $methodName = 'inject' . $methodNamePart;
241 $target->$methodName($dependency);
242 } elseif ($objectReflection->hasProperty($name)) {
243 $property = $objectReflection->getProperty($name);
244 $property->setAccessible(TRUE);
245 $property->setValue($target, $dependency);
246 } else {
247 throw new \RuntimeException('Could not inject ' . $name . ' into object of type ' . get_class($target));
248 }
249 }
250 }