1<?php 2/* 3 * This file is part of the PHPUnit_MockObject 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 11/** 12 * Main matcher which defines a full expectation using method, parameter and 13 * invocation matchers. 14 * This matcher encapsulates all the other matchers and allows the builder to 15 * set the specific matchers when the appropriate methods are called (once(), 16 * where() etc.). 17 * 18 * All properties are public so that they can easily be accessed by the builder. 19 * 20 * @since Class available since Release 1.0.0 21 */ 22class PHPUnit_Framework_MockObject_Matcher implements PHPUnit_Framework_MockObject_Matcher_Invocation 23{ 24 /** 25 * @var PHPUnit_Framework_MockObject_Matcher_Invocation 26 */ 27 public $invocationMatcher; 28 29 /** 30 * @var mixed 31 */ 32 public $afterMatchBuilderId = null; 33 34 /** 35 * @var bool 36 */ 37 public $afterMatchBuilderIsInvoked = false; 38 39 /** 40 * @var PHPUnit_Framework_MockObject_Matcher_MethodName 41 */ 42 public $methodNameMatcher = null; 43 44 /** 45 * @var PHPUnit_Framework_MockObject_Matcher_Parameters 46 */ 47 public $parametersMatcher = null; 48 49 /** 50 * @var PHPUnit_Framework_MockObject_Stub 51 */ 52 public $stub = null; 53 54 /** 55 * @param PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher 56 */ 57 public function __construct(PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher) 58 { 59 $this->invocationMatcher = $invocationMatcher; 60 } 61 62 /** 63 * @return string 64 */ 65 public function toString() 66 { 67 $list = []; 68 69 if ($this->invocationMatcher !== null) { 70 $list[] = $this->invocationMatcher->toString(); 71 } 72 73 if ($this->methodNameMatcher !== null) { 74 $list[] = 'where ' . $this->methodNameMatcher->toString(); 75 } 76 77 if ($this->parametersMatcher !== null) { 78 $list[] = 'and ' . $this->parametersMatcher->toString(); 79 } 80 81 if ($this->afterMatchBuilderId !== null) { 82 $list[] = 'after ' . $this->afterMatchBuilderId; 83 } 84 85 if ($this->stub !== null) { 86 $list[] = 'will ' . $this->stub->toString(); 87 } 88 89 return implode(' ', $list); 90 } 91 92 /** 93 * @param PHPUnit_Framework_MockObject_Invocation $invocation 94 * 95 * @return mixed 96 */ 97 public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation) 98 { 99 if ($this->invocationMatcher === null) { 100 throw new PHPUnit_Framework_MockObject_RuntimeException( 101 'No invocation matcher is set' 102 ); 103 } 104 105 if ($this->methodNameMatcher === null) { 106 throw new PHPUnit_Framework_MockObject_RuntimeException('No method matcher is set'); 107 } 108 109 if ($this->afterMatchBuilderId !== null) { 110 $builder = $invocation->object 111 ->__phpunit_getInvocationMocker() 112 ->lookupId($this->afterMatchBuilderId); 113 114 if (!$builder) { 115 throw new PHPUnit_Framework_MockObject_RuntimeException( 116 sprintf( 117 'No builder found for match builder identification <%s>', 118 $this->afterMatchBuilderId 119 ) 120 ); 121 } 122 123 $matcher = $builder->getMatcher(); 124 125 if ($matcher && $matcher->invocationMatcher->hasBeenInvoked()) { 126 $this->afterMatchBuilderIsInvoked = true; 127 } 128 } 129 130 $this->invocationMatcher->invoked($invocation); 131 132 try { 133 if ($this->parametersMatcher !== null && 134 !$this->parametersMatcher->matches($invocation)) { 135 $this->parametersMatcher->verify(); 136 } 137 } catch (PHPUnit_Framework_ExpectationFailedException $e) { 138 throw new PHPUnit_Framework_ExpectationFailedException( 139 sprintf( 140 "Expectation failed for %s when %s\n%s", 141 $this->methodNameMatcher->toString(), 142 $this->invocationMatcher->toString(), 143 $e->getMessage() 144 ), 145 $e->getComparisonFailure() 146 ); 147 } 148 149 if ($this->stub) { 150 return $this->stub->invoke($invocation); 151 } 152 153 return $invocation->generateReturnValue(); 154 } 155 156 /** 157 * @param PHPUnit_Framework_MockObject_Invocation $invocation 158 * 159 * @return bool 160 */ 161 public function matches(PHPUnit_Framework_MockObject_Invocation $invocation) 162 { 163 if ($this->afterMatchBuilderId !== null) { 164 $builder = $invocation->object 165 ->__phpunit_getInvocationMocker() 166 ->lookupId($this->afterMatchBuilderId); 167 168 if (!$builder) { 169 throw new PHPUnit_Framework_MockObject_RuntimeException( 170 sprintf( 171 'No builder found for match builder identification <%s>', 172 $this->afterMatchBuilderId 173 ) 174 ); 175 } 176 177 $matcher = $builder->getMatcher(); 178 179 if (!$matcher) { 180 return false; 181 } 182 183 if (!$matcher->invocationMatcher->hasBeenInvoked()) { 184 return false; 185 } 186 } 187 188 if ($this->invocationMatcher === null) { 189 throw new PHPUnit_Framework_MockObject_RuntimeException( 190 'No invocation matcher is set' 191 ); 192 } 193 194 if ($this->methodNameMatcher === null) { 195 throw new PHPUnit_Framework_MockObject_RuntimeException('No method matcher is set'); 196 } 197 198 if (!$this->invocationMatcher->matches($invocation)) { 199 return false; 200 } 201 202 try { 203 if (!$this->methodNameMatcher->matches($invocation)) { 204 return false; 205 } 206 } catch (PHPUnit_Framework_ExpectationFailedException $e) { 207 throw new PHPUnit_Framework_ExpectationFailedException( 208 sprintf( 209 "Expectation failed for %s when %s\n%s", 210 $this->methodNameMatcher->toString(), 211 $this->invocationMatcher->toString(), 212 $e->getMessage() 213 ), 214 $e->getComparisonFailure() 215 ); 216 } 217 218 return true; 219 } 220 221 /** 222 * @throws PHPUnit_Framework_MockObject_RuntimeException 223 * @throws PHPUnit_Framework_ExpectationFailedException 224 */ 225 public function verify() 226 { 227 if ($this->invocationMatcher === null) { 228 throw new PHPUnit_Framework_MockObject_RuntimeException( 229 'No invocation matcher is set' 230 ); 231 } 232 233 if ($this->methodNameMatcher === null) { 234 throw new PHPUnit_Framework_MockObject_RuntimeException('No method matcher is set'); 235 } 236 237 try { 238 $this->invocationMatcher->verify(); 239 240 if ($this->parametersMatcher === null) { 241 $this->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_AnyParameters; 242 } 243 244 $invocationIsAny = $this->invocationMatcher instanceof PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount; 245 $invocationIsNever = $this->invocationMatcher instanceof PHPUnit_Framework_MockObject_Matcher_InvokedCount && $this->invocationMatcher->isNever(); 246 247 if (!$invocationIsAny && !$invocationIsNever) { 248 $this->parametersMatcher->verify(); 249 } 250 } catch (PHPUnit_Framework_ExpectationFailedException $e) { 251 throw new PHPUnit_Framework_ExpectationFailedException( 252 sprintf( 253 "Expectation failed for %s when %s.\n%s", 254 $this->methodNameMatcher->toString(), 255 $this->invocationMatcher->toString(), 256 PHPUnit_Framework_TestFailure::exceptionToString($e) 257 ) 258 ); 259 } 260 } 261 262 /** 263 * @since Method available since Release 1.2.4 264 */ 265 public function hasMatchers() 266 { 267 if ($this->invocationMatcher !== null && 268 !$this->invocationMatcher instanceof PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount) { 269 return true; 270 } 271 272 return false; 273 } 274} 275