Matcher.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. /*
  3. * This file is part of the phpunit-mock-objects package.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. use PHPUnit\Framework\ExpectationFailedException;
  11. use PHPUnit\Framework\TestFailure;
  12. /**
  13. * Main matcher which defines a full expectation using method, parameter and
  14. * invocation matchers.
  15. * This matcher encapsulates all the other matchers and allows the builder to
  16. * set the specific matchers when the appropriate methods are called (once(),
  17. * where() etc.).
  18. *
  19. * All properties are public so that they can easily be accessed by the builder.
  20. */
  21. class PHPUnit_Framework_MockObject_Matcher implements PHPUnit_Framework_MockObject_Matcher_Invocation
  22. {
  23. /**
  24. * @var PHPUnit_Framework_MockObject_Matcher_Invocation
  25. */
  26. public $invocationMatcher;
  27. /**
  28. * @var mixed
  29. */
  30. public $afterMatchBuilderId = null;
  31. /**
  32. * @var bool
  33. */
  34. public $afterMatchBuilderIsInvoked = false;
  35. /**
  36. * @var PHPUnit_Framework_MockObject_Matcher_MethodName
  37. */
  38. public $methodNameMatcher = null;
  39. /**
  40. * @var PHPUnit_Framework_MockObject_Matcher_Parameters
  41. */
  42. public $parametersMatcher = null;
  43. /**
  44. * @var PHPUnit_Framework_MockObject_Stub
  45. */
  46. public $stub = null;
  47. /**
  48. * @param PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher
  49. */
  50. public function __construct(PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher)
  51. {
  52. $this->invocationMatcher = $invocationMatcher;
  53. }
  54. /**
  55. * @return string
  56. */
  57. public function toString()
  58. {
  59. $list = [];
  60. if ($this->invocationMatcher !== null) {
  61. $list[] = $this->invocationMatcher->toString();
  62. }
  63. if ($this->methodNameMatcher !== null) {
  64. $list[] = 'where ' . $this->methodNameMatcher->toString();
  65. }
  66. if ($this->parametersMatcher !== null) {
  67. $list[] = 'and ' . $this->parametersMatcher->toString();
  68. }
  69. if ($this->afterMatchBuilderId !== null) {
  70. $list[] = 'after ' . $this->afterMatchBuilderId;
  71. }
  72. if ($this->stub !== null) {
  73. $list[] = 'will ' . $this->stub->toString();
  74. }
  75. return implode(' ', $list);
  76. }
  77. /**
  78. * @param PHPUnit_Framework_MockObject_Invocation $invocation
  79. *
  80. * @return mixed
  81. */
  82. public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
  83. {
  84. if ($this->invocationMatcher === null) {
  85. throw new PHPUnit_Framework_MockObject_RuntimeException(
  86. 'No invocation matcher is set'
  87. );
  88. }
  89. if ($this->methodNameMatcher === null) {
  90. throw new PHPUnit_Framework_MockObject_RuntimeException('No method matcher is set');
  91. }
  92. if ($this->afterMatchBuilderId !== null) {
  93. $builder = $invocation->object
  94. ->__phpunit_getInvocationMocker()
  95. ->lookupId($this->afterMatchBuilderId);
  96. if (!$builder) {
  97. throw new PHPUnit_Framework_MockObject_RuntimeException(
  98. sprintf(
  99. 'No builder found for match builder identification <%s>',
  100. $this->afterMatchBuilderId
  101. )
  102. );
  103. }
  104. $matcher = $builder->getMatcher();
  105. if ($matcher && $matcher->invocationMatcher->hasBeenInvoked()) {
  106. $this->afterMatchBuilderIsInvoked = true;
  107. }
  108. }
  109. $this->invocationMatcher->invoked($invocation);
  110. try {
  111. if ($this->parametersMatcher !== null &&
  112. !$this->parametersMatcher->matches($invocation)) {
  113. $this->parametersMatcher->verify();
  114. }
  115. } catch (ExpectationFailedException $e) {
  116. throw new ExpectationFailedException(
  117. sprintf(
  118. "Expectation failed for %s when %s\n%s",
  119. $this->methodNameMatcher->toString(),
  120. $this->invocationMatcher->toString(),
  121. $e->getMessage()
  122. ),
  123. $e->getComparisonFailure()
  124. );
  125. }
  126. if ($this->stub) {
  127. return $this->stub->invoke($invocation);
  128. }
  129. return $invocation->generateReturnValue();
  130. }
  131. /**
  132. * @param PHPUnit_Framework_MockObject_Invocation $invocation
  133. *
  134. * @return bool
  135. */
  136. public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
  137. {
  138. if ($this->afterMatchBuilderId !== null) {
  139. $builder = $invocation->object
  140. ->__phpunit_getInvocationMocker()
  141. ->lookupId($this->afterMatchBuilderId);
  142. if (!$builder) {
  143. throw new PHPUnit_Framework_MockObject_RuntimeException(
  144. sprintf(
  145. 'No builder found for match builder identification <%s>',
  146. $this->afterMatchBuilderId
  147. )
  148. );
  149. }
  150. $matcher = $builder->getMatcher();
  151. if (!$matcher) {
  152. return false;
  153. }
  154. if (!$matcher->invocationMatcher->hasBeenInvoked()) {
  155. return false;
  156. }
  157. }
  158. if ($this->invocationMatcher === null) {
  159. throw new PHPUnit_Framework_MockObject_RuntimeException(
  160. 'No invocation matcher is set'
  161. );
  162. }
  163. if ($this->methodNameMatcher === null) {
  164. throw new PHPUnit_Framework_MockObject_RuntimeException('No method matcher is set');
  165. }
  166. if (!$this->invocationMatcher->matches($invocation)) {
  167. return false;
  168. }
  169. try {
  170. if (!$this->methodNameMatcher->matches($invocation)) {
  171. return false;
  172. }
  173. } catch (ExpectationFailedException $e) {
  174. throw new ExpectationFailedException(
  175. sprintf(
  176. "Expectation failed for %s when %s\n%s",
  177. $this->methodNameMatcher->toString(),
  178. $this->invocationMatcher->toString(),
  179. $e->getMessage()
  180. ),
  181. $e->getComparisonFailure()
  182. );
  183. }
  184. return true;
  185. }
  186. /**
  187. * @throws PHPUnit_Framework_MockObject_RuntimeException
  188. * @throws ExpectationFailedException
  189. */
  190. public function verify()
  191. {
  192. if ($this->invocationMatcher === null) {
  193. throw new PHPUnit_Framework_MockObject_RuntimeException(
  194. 'No invocation matcher is set'
  195. );
  196. }
  197. if ($this->methodNameMatcher === null) {
  198. throw new PHPUnit_Framework_MockObject_RuntimeException('No method matcher is set');
  199. }
  200. try {
  201. $this->invocationMatcher->verify();
  202. if ($this->parametersMatcher === null) {
  203. $this->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_AnyParameters;
  204. }
  205. $invocationIsAny = $this->invocationMatcher instanceof PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
  206. $invocationIsNever = $this->invocationMatcher instanceof PHPUnit_Framework_MockObject_Matcher_InvokedCount && $this->invocationMatcher->isNever();
  207. if (!$invocationIsAny && !$invocationIsNever) {
  208. $this->parametersMatcher->verify();
  209. }
  210. } catch (ExpectationFailedException $e) {
  211. throw new ExpectationFailedException(
  212. sprintf(
  213. "Expectation failed for %s when %s.\n%s",
  214. $this->methodNameMatcher->toString(),
  215. $this->invocationMatcher->toString(),
  216. TestFailure::exceptionToString($e)
  217. )
  218. );
  219. }
  220. }
  221. public function hasMatchers()
  222. {
  223. if ($this->invocationMatcher !== null &&
  224. !$this->invocationMatcher instanceof PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount) {
  225. return true;
  226. }
  227. return false;
  228. }
  229. }