PageRenderTime 26ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Mockery.php

https://github.com/DocAl/mockery
PHP | 347 lines | 182 code | 27 blank | 138 comment | 18 complexity | 5cbb7256dddde248c131ed2268f14e6b MD5 | raw file
  1. <?php
  2. /**
  3. * Mockery
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://github.com/padraic/mockery/blob/master/LICENSE
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to padraic@php.net so we can send you a copy immediately.
  14. *
  15. * @category Mockery
  16. * @package Mockery
  17. * @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
  18. * @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
  19. */
  20. class Mockery
  21. {
  22. const BLOCKS = 'Mockery_Forward_Blocks';
  23. /**
  24. * Global container to hold all mocks for the current unit test running
  25. *
  26. * @var \Mockery\Container
  27. */
  28. protected static $_container = null;
  29. /**
  30. * Global configuration handler containing configuration options
  31. *
  32. * @var \Mockery\Configuration
  33. */
  34. protected static $_config = null;
  35. /**
  36. * Static shortcut to \Mockery\Container::mock()
  37. *
  38. * @return \Mockery\MockInterface
  39. */
  40. public static function mock()
  41. {
  42. if (is_null(self::$_container)) {
  43. self::$_container = new \Mockery\Container;
  44. }
  45. $args = func_get_args();
  46. return call_user_func_array(array(self::$_container, 'mock'), $args);
  47. }
  48. public static function instanceMock()
  49. {
  50. if (is_null(self::$_container)) {
  51. self::$_container = new \Mockery\Container;
  52. }
  53. $args = func_get_args();
  54. return call_user_func_array(array(self::$_container, 'instanceMock'), $args);
  55. }
  56. /**
  57. * Static shortcut to closing up and verifying all mocks in the global
  58. * container, and resetting the container static variable to null
  59. *
  60. * @return void
  61. */
  62. public static function close()
  63. {
  64. if (is_null(self::$_container)) return;
  65. self::$_container->mockery_teardown();
  66. self::$_container->mockery_close();
  67. self::$_container = null;
  68. }
  69. /**
  70. * Static fetching of a mock associated with a name or explicit class poser
  71. */
  72. public static function fetchMock($name)
  73. {
  74. return self::$_container->fetchMock($name);
  75. }
  76. /**
  77. * Get the container
  78. */
  79. public static function getContainer()
  80. {
  81. return self::$_container;
  82. }
  83. /**
  84. * Set the container
  85. */
  86. public static function setContainer(Mockery\Container $container)
  87. {
  88. return self::$_container = $container;
  89. }
  90. /**
  91. * Reset the container to NULL
  92. */
  93. public static function resetContainer()
  94. {
  95. self::$_container = null;
  96. }
  97. /**
  98. * Return instance of ANY matcher
  99. *
  100. * @return
  101. */
  102. public static function any()
  103. {
  104. $return = new \Mockery\Matcher\Any();
  105. return $return;
  106. }
  107. /**
  108. * Return instance of TYPE matcher
  109. *
  110. * @return
  111. */
  112. public static function type($expected)
  113. {
  114. $return = new \Mockery\Matcher\Type($expected);
  115. return $return;
  116. }
  117. /**
  118. * Return instance of DUCKTYPE matcher
  119. *
  120. * @return
  121. */
  122. public static function ducktype()
  123. {
  124. $return = new \Mockery\Matcher\Ducktype(func_get_args());
  125. return $return;
  126. }
  127. /**
  128. * Return instance of SUBSET matcher
  129. *
  130. * @return
  131. */
  132. public static function subset(array $part)
  133. {
  134. $return = new \Mockery\Matcher\Subset($part);
  135. return $return;
  136. }
  137. /**
  138. * Return instance of CONTAINS matcher
  139. *
  140. * @return
  141. */
  142. public static function contains()
  143. {
  144. $return = new \Mockery\Matcher\Contains(func_get_args());
  145. return $return;
  146. }
  147. /**
  148. * Return instance of HASKEY matcher
  149. *
  150. * @return
  151. */
  152. public static function hasKey($key)
  153. {
  154. $return = new \Mockery\Matcher\HasKey($key);
  155. return $return;
  156. }
  157. /**
  158. * Return instance of HASVALUE matcher
  159. *
  160. * @return
  161. */
  162. public static function hasValue($val)
  163. {
  164. $return = new \Mockery\Matcher\HasValue($val);
  165. return $return;
  166. }
  167. /**
  168. * Return instance of CLOSURE matcher
  169. *
  170. * @return
  171. */
  172. public static function on($closure)
  173. {
  174. $return = new \Mockery\Matcher\Closure($closure);
  175. return $return;
  176. }
  177. /**
  178. * Return instance of MUSTBE matcher
  179. *
  180. * @return
  181. */
  182. public static function mustBe($expected)
  183. {
  184. $return = new \Mockery\Matcher\MustBe($expected);
  185. return $return;
  186. }
  187. /**
  188. * Return instance of NOT matcher
  189. *
  190. * @return
  191. */
  192. public static function not($expected)
  193. {
  194. $return = new \Mockery\Matcher\Not($expected);
  195. return $return;
  196. }
  197. /**
  198. * Return instance of ANYOF matcher
  199. *
  200. * @return
  201. */
  202. public static function anyOf()
  203. {
  204. $return = new \Mockery\Matcher\AnyOf(func_get_args());
  205. return $return;
  206. }
  207. /**
  208. * Return instance of NOTANYOF matcher
  209. *
  210. * @return
  211. */
  212. public static function notAnyOf()
  213. {
  214. $return = new \Mockery\Matcher\NotAnyOf(func_get_args());
  215. return $return;
  216. }
  217. /**
  218. * Get the global configuration container
  219. */
  220. public static function getConfiguration()
  221. {
  222. if (is_null(self::$_config)) {
  223. self::$_config = new \Mockery\Configuration;
  224. }
  225. return self::$_config;
  226. }
  227. /**
  228. * Utility method to format method name and args into a string
  229. *
  230. * @param string $method
  231. * @param array $args
  232. * @return string
  233. */
  234. public static function formatArgs($method, array $args = null)
  235. {
  236. $return = $method . '(';
  237. if ($args && !empty($args)) {
  238. $parts = array();
  239. foreach($args as $arg) {
  240. if (is_object($arg)) {
  241. $parts[] = get_class($arg);
  242. } elseif (is_int($arg) || is_float($arg)) {
  243. $parts[] = $arg;
  244. } elseif (is_array($arg)) {
  245. $parts[] = 'Array';
  246. } else {
  247. $parts[] = '"' . (string) $arg . '"';
  248. }
  249. }
  250. $return .= implode(', ', $parts); // TODO: improve format
  251. }
  252. $return .= ')';
  253. return $return;
  254. }
  255. /**
  256. * Utility function to parse shouldReceive() arguments and generate
  257. * expectations from such as needed.
  258. *
  259. * @param \Mockery\MockInterface
  260. * @param array $args
  261. * @return \Mockery\CompositeExpectation
  262. */
  263. public static function parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add)
  264. {
  265. $composite = new \Mockery\CompositeExpectation;
  266. foreach ($args as $arg) {
  267. if (is_array($arg)) {
  268. foreach($arg as $k=>$v) {
  269. $expectation = self::_buildDemeterChain($mock, $k, $add)->andReturn($v);
  270. $composite->add($expectation);
  271. }
  272. } elseif (is_string($arg)) {
  273. $expectation = self::_buildDemeterChain($mock, $arg, $add);
  274. $composite->add($expectation);
  275. }
  276. }
  277. return $composite;
  278. }
  279. /**
  280. * Sets up expectations on the members of the CompositeExpectation and
  281. * builds up any demeter chain that was passed to shouldReceive
  282. *
  283. * @param \Mockery\MockInterface $mock
  284. * @param string $arg
  285. * @param Closure $add
  286. * @return \Mockery\ExpectationDirector
  287. */
  288. protected static function _buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add)
  289. {
  290. $container = $mock->mockery_getContainer();
  291. $names = explode('->', $arg);
  292. reset($names);
  293. if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()
  294. && !in_array(current($names), $mock->mockery_getMockableMethods())) {
  295. throw new \Mockery\Exception(
  296. 'Mockery\'s configuration currently forbids mocking the method '
  297. . current($names) . ' as it does not exist on the class or object '
  298. . 'being mocked'
  299. );
  300. }
  301. $exp = null;
  302. $nextExp = function ($n) use ($add) {return $add($n);};
  303. while (true) {
  304. $method = array_shift($names);
  305. $exp = $mock->mockery_getExpectationsFor($method);
  306. $needNew = false;
  307. if (is_null($exp) || empty($names)) {
  308. $needNew = true;
  309. }
  310. if ($needNew) $exp = $nextExp($method);
  311. if (empty($names)) break;
  312. if ($needNew) {
  313. $mock = $container->mock('demeter_' . $method);
  314. $exp->withNoArgs()->andReturn($mock);
  315. }
  316. $nextExp = function ($n) use ($mock) {return $mock->shouldReceive($n);};
  317. }
  318. return $exp;
  319. }
  320. }