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 * Builder for mocked or stubbed invocations. 13 * 14 * Provides methods for building expectations without having to resort to 15 * instantiating the various matchers manually. These methods also form a 16 * more natural way of reading the expectation. This class should be together 17 * with the test case PHPUnit_Framework_MockObject_TestCase. 18 * 19 * @since Class available since Release 1.0.0 20 */ 21class PHPUnit_Framework_MockObject_Builder_InvocationMocker implements PHPUnit_Framework_MockObject_Builder_MethodNameMatch 22{ 23 /** 24 * @var PHPUnit_Framework_MockObject_Stub_MatcherCollection 25 */ 26 protected $collection; 27 28 /** 29 * @var PHPUnit_Framework_MockObject_Matcher 30 */ 31 protected $matcher; 32 33 /** 34 * @var string[] 35 */ 36 private $configurableMethods = []; 37 38 /** 39 * @param PHPUnit_Framework_MockObject_Stub_MatcherCollection $collection 40 * @param PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher 41 * @param array $configurableMethods 42 */ 43 public function __construct(PHPUnit_Framework_MockObject_Stub_MatcherCollection $collection, PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher, array $configurableMethods) 44 { 45 $this->collection = $collection; 46 $this->matcher = new PHPUnit_Framework_MockObject_Matcher( 47 $invocationMatcher 48 ); 49 50 $this->collection->addMatcher($this->matcher); 51 52 $this->configurableMethods = $configurableMethods; 53 } 54 55 /** 56 * @return PHPUnit_Framework_MockObject_Matcher 57 */ 58 public function getMatcher() 59 { 60 return $this->matcher; 61 } 62 63 /** 64 * @param mixed $id 65 * 66 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 67 */ 68 public function id($id) 69 { 70 $this->collection->registerId($id, $this); 71 72 return $this; 73 } 74 75 /** 76 * @param PHPUnit_Framework_MockObject_Stub $stub 77 * 78 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 79 */ 80 public function will(PHPUnit_Framework_MockObject_Stub $stub) 81 { 82 $this->matcher->stub = $stub; 83 84 return $this; 85 } 86 87 /** 88 * @param mixed $value 89 * @param mixed $nextValues, ... 90 * 91 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 92 */ 93 public function willReturn($value, ...$nextValues) 94 { 95 $stub = count($nextValues) === 0 ? 96 new PHPUnit_Framework_MockObject_Stub_Return($value) : 97 new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls( 98 array_merge([$value], $nextValues) 99 ); 100 101 return $this->will($stub); 102 } 103 104 /** 105 * @param mixed $reference 106 * 107 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 108 */ 109 public function willReturnReference(&$reference) 110 { 111 $stub = new PHPUnit_Framework_MockObject_Stub_ReturnReference($reference); 112 113 return $this->will($stub); 114 } 115 116 /** 117 * @param array $valueMap 118 * 119 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 120 */ 121 public function willReturnMap(array $valueMap) 122 { 123 $stub = new PHPUnit_Framework_MockObject_Stub_ReturnValueMap( 124 $valueMap 125 ); 126 127 return $this->will($stub); 128 } 129 130 /** 131 * @param mixed $argumentIndex 132 * 133 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 134 */ 135 public function willReturnArgument($argumentIndex) 136 { 137 $stub = new PHPUnit_Framework_MockObject_Stub_ReturnArgument( 138 $argumentIndex 139 ); 140 141 return $this->will($stub); 142 } 143 144 /** 145 * @param callable $callback 146 * 147 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 148 */ 149 public function willReturnCallback($callback) 150 { 151 $stub = new PHPUnit_Framework_MockObject_Stub_ReturnCallback( 152 $callback 153 ); 154 155 return $this->will($stub); 156 } 157 158 /** 159 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 160 */ 161 public function willReturnSelf() 162 { 163 $stub = new PHPUnit_Framework_MockObject_Stub_ReturnSelf; 164 165 return $this->will($stub); 166 } 167 168 /** 169 * @param mixed $values, ... 170 * 171 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 172 */ 173 public function willReturnOnConsecutiveCalls(...$values) 174 { 175 $stub = new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($values); 176 177 return $this->will($stub); 178 } 179 180 /** 181 * @param Exception $exception 182 * 183 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 184 */ 185 public function willThrowException(Exception $exception) 186 { 187 $stub = new PHPUnit_Framework_MockObject_Stub_Exception($exception); 188 189 return $this->will($stub); 190 } 191 192 /** 193 * @param mixed $id 194 * 195 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 196 */ 197 public function after($id) 198 { 199 $this->matcher->afterMatchBuilderId = $id; 200 201 return $this; 202 } 203 204 /** 205 * Validate that a parameters matcher can be defined, throw exceptions otherwise. 206 * 207 * @throws PHPUnit_Framework_MockObject_RuntimeException 208 */ 209 private function canDefineParameters() 210 { 211 if ($this->matcher->methodNameMatcher === null) { 212 throw new PHPUnit_Framework_MockObject_RuntimeException( 213 'Method name matcher is not defined, cannot define parameter ' . 214 'matcher without one' 215 ); 216 } 217 218 if ($this->matcher->parametersMatcher !== null) { 219 throw new PHPUnit_Framework_MockObject_RuntimeException( 220 'Parameter matcher is already defined, cannot redefine' 221 ); 222 } 223 } 224 225 /** 226 * @param array ...$arguments 227 * 228 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 229 */ 230 public function with(...$arguments) 231 { 232 $this->canDefineParameters(); 233 234 $this->matcher->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_Parameters($arguments); 235 236 return $this; 237 } 238 239 /** 240 * @param array ...$arguments 241 * 242 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 243 */ 244 public function withConsecutive(...$arguments) 245 { 246 $this->canDefineParameters(); 247 248 $this->matcher->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters($arguments); 249 250 return $this; 251 } 252 253 /** 254 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 255 */ 256 public function withAnyParameters() 257 { 258 $this->canDefineParameters(); 259 260 $this->matcher->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_AnyParameters; 261 262 return $this; 263 } 264 265 /** 266 * @param PHPUnit_Framework_Constraint|string $constraint 267 * 268 * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker 269 */ 270 public function method($constraint) 271 { 272 if ($this->matcher->methodNameMatcher !== null) { 273 throw new PHPUnit_Framework_MockObject_RuntimeException( 274 'Method name matcher is already defined, cannot redefine' 275 ); 276 } 277 278 if (is_string($constraint) && !in_array(strtolower($constraint), $this->configurableMethods)) { 279 throw new PHPUnit_Framework_MockObject_RuntimeException( 280 sprintf( 281 'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static', 282 $constraint 283 ) 284 ); 285 } 286 287 $this->matcher->methodNameMatcher = new PHPUnit_Framework_MockObject_Matcher_MethodName($constraint); 288 289 return $this; 290 } 291} 292