MockerChain.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\test;
  9. /**
  10. * Mocker chain is used to aid in assertion of method calls.
  11. *
  12. * Asserting if `method1` was not called
  13. * {{{
  14. * $mock = new \lithium\tests\mocks\test\mockStdClass\Mock();
  15. * $this->assertFalse(Mocker::chain($mock)->called('method1')->success());
  16. * }}}
  17. *
  18. * Asserting if `method1` was called 2 times
  19. * {{{
  20. * $mock = new \lithium\tests\mocks\test\mockStdClass\Mock();
  21. * $this->assertTrue(Mocker::chain($mock)->called('method1')->eq(2)->success());
  22. * }}}
  23. *
  24. * Asserting if `method2` was called after `method1`
  25. * {{{
  26. * $mock = new \lithium\tests\mocks\test\mockStdClass\Mock();
  27. * $this->assertTrue(Mocker::chain($mock)->called('method1')->called('method2')->success());
  28. * }}}
  29. *
  30. * Asserting if `method2` was called after `method1`, and `method2` had specific arguments.
  31. * {{{
  32. * $mock = new \lithium\tests\mocks\test\mockStdClass\Mock();
  33. * $this->assertTrue(Mocker::chain($mock)
  34. * ->called('method1')
  35. * ->called('method2')->with('foo', 'bar')
  36. * ->success());
  37. * }}}
  38. */
  39. class MockerChain extends \lithium\core\Object {
  40. /**
  41. * Data to be used in the class.
  42. *
  43. * `results` Cached mock results
  44. * `method` Method we are asserting
  45. * `args` Args we are asserting
  46. * `success` Success flag
  47. * `callTime` Last method call
  48. *
  49. * @var array
  50. */
  51. protected $_data = array(
  52. 'results' => null,
  53. 'method' => false,
  54. 'args' => false,
  55. 'success' => true,
  56. 'callTime' => 0,
  57. );
  58. /**
  59. * Saves the results from the mock.
  60. *
  61. * @param array $results Results from the mock
  62. */
  63. public function __construct($results) {
  64. $this->_data['results'] = $results;
  65. }
  66. /**
  67. * Validates that a given methodis called a set number of times.
  68. *
  69. * @param string $comparison Comparison type 'gt', 'gte', 'lt', 'lte', or 'eq'.
  70. * @param array $args The first argument is the expected result.
  71. * @return object
  72. */
  73. public function __call($comparison, $args) {
  74. $methodExists = in_array($comparison, array('gt', 'gte', 'lt', 'lte', 'eq'), true);
  75. if (!$this->_data['success'] || !$methodExists) {
  76. return $this;
  77. }
  78. if (count($args) === 0 || !is_int($args[0])) {
  79. $this->_data['success'] = false;
  80. return $this;
  81. }
  82. $result = 0;
  83. $expected = $args[0];
  84. $method = $this->_data['method'];
  85. $args = $this->_data['args'];
  86. foreach ($this->_data['results'][$method] as $call) {
  87. $correctTime = $this->_data['callTime'] <= $call['time'];
  88. $correctArgs = !is_array($args) || $args === $call['args'];
  89. if ($correctTime && $correctArgs) {
  90. $this->_data['callTime'] = $call['time'];
  91. $result++;
  92. }
  93. }
  94. switch ($comparison) {
  95. case 'gt':
  96. $this->_data['success'] = $result > $expected;
  97. break;
  98. case 'gte':
  99. $this->_data['success'] = $result >= $expected;
  100. break;
  101. case 'lt':
  102. $this->_data['success'] = $result < $expected;
  103. break;
  104. case 'lte':
  105. $this->_data['success'] = $result <= $expected;
  106. break;
  107. case 'eq':
  108. $this->_data['success'] = $result === $expected;
  109. break;
  110. }
  111. return $this;
  112. }
  113. /**
  114. * Custom check to determine if our given magic methods can be responded to.
  115. *
  116. * @param string $method Method name.
  117. * @param bool $internal Interal call or not.
  118. * @return bool
  119. */
  120. public function respondsTo($method, $internal = false) {
  121. $methodExists = in_array($method, array('gt', 'gte', 'lt', 'lte', 'eq'), true);
  122. return $methodExists || parent::respondsTo($method, $internal);
  123. }
  124. /**
  125. * Valides the method was called after the last call.
  126. *
  127. * @param string $method Method to assert
  128. * @return object
  129. */
  130. public function called($method) {
  131. if (!$this->_data['success']) {
  132. return $this;
  133. }
  134. $this->_data['method'] = $method;
  135. $this->_data['args'] = false;
  136. if (!isset($this->_data['results'][$method])) {
  137. $this->_data['success'] = false;
  138. return $this;
  139. }
  140. foreach ($this->_data['results'][$method] as $call) {
  141. if ($this->_data['callTime'] < $call['time']) {
  142. $this->_data['callTime'] = $call['time'];
  143. return $this;
  144. }
  145. }
  146. $this->_data['success'] = false;
  147. return $this;
  148. }
  149. /**
  150. * Will further narrow down the original 'called' method.
  151. *
  152. * Valides the cached method name was called with these args
  153. *
  154. * @param mixed $arg,... Optional arguments to test against
  155. * @return object
  156. */
  157. public function with() {
  158. if (!$this->_data['success']) {
  159. return $this;
  160. }
  161. $method = $this->_data['method'];
  162. $this->_data['args'] = $args = func_get_args();
  163. foreach ($this->_data['results'][$method] as $call) {
  164. $correctTime = $this->_data['callTime'] <= $call['time'];
  165. $correctArgs = $args === $call['args'];
  166. if ($correctTime && $correctArgs) {
  167. $this->_data['callTime'] = $call['time'];
  168. return $this;
  169. }
  170. }
  171. $this->_data['success'] = false;
  172. return $this;
  173. }
  174. /**
  175. * Gives back the success flag
  176. *
  177. * @return bool
  178. */
  179. public function success() {
  180. $success = $this->_data['success'];
  181. $this->_data = array(
  182. 'results' => $this->_data['results'],
  183. 'method' => false,
  184. 'args' => false,
  185. 'success' => true,
  186. 'callTime' => 0,
  187. );
  188. return $success;
  189. }
  190. }
  191. ?>