Chris@14
|
1 <?php
|
Chris@14
|
2 /*
|
Chris@14
|
3 * This file is part of the phpunit-mock-objects package.
|
Chris@14
|
4 *
|
Chris@14
|
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
|
Chris@14
|
6 *
|
Chris@14
|
7 * For the full copyright and license information, please view the LICENSE
|
Chris@14
|
8 * file that was distributed with this source code.
|
Chris@14
|
9 */
|
Chris@14
|
10 namespace PHPUnit\Framework\MockObject\Matcher;
|
Chris@14
|
11
|
Chris@14
|
12 use PHPUnit\Framework\Constraint\Constraint;
|
Chris@14
|
13 use PHPUnit\Framework\Constraint\IsAnything;
|
Chris@14
|
14 use PHPUnit\Framework\Constraint\IsEqual;
|
Chris@14
|
15 use PHPUnit\Framework\ExpectationFailedException;
|
Chris@14
|
16 use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
|
Chris@14
|
17
|
Chris@14
|
18 /**
|
Chris@14
|
19 * Invocation matcher which looks for specific parameters in the invocations.
|
Chris@14
|
20 *
|
Chris@14
|
21 * Checks the parameters of all incoming invocations, the parameter list is
|
Chris@14
|
22 * checked against the defined constraints in $parameters. If the constraint
|
Chris@14
|
23 * is met it will return true in matches().
|
Chris@14
|
24 */
|
Chris@14
|
25 class Parameters extends StatelessInvocation
|
Chris@14
|
26 {
|
Chris@14
|
27 /**
|
Chris@14
|
28 * @var Constraint[]
|
Chris@14
|
29 */
|
Chris@14
|
30 private $parameters = [];
|
Chris@14
|
31
|
Chris@14
|
32 /**
|
Chris@14
|
33 * @var BaseInvocation
|
Chris@14
|
34 */
|
Chris@14
|
35 private $invocation;
|
Chris@14
|
36
|
Chris@14
|
37 /**
|
Chris@14
|
38 * @var ExpectationFailedException
|
Chris@14
|
39 */
|
Chris@14
|
40 private $parameterVerificationResult;
|
Chris@14
|
41
|
Chris@14
|
42 /**
|
Chris@14
|
43 * @param array $parameters
|
Chris@14
|
44 *
|
Chris@14
|
45 * @throws \PHPUnit\Framework\Exception
|
Chris@14
|
46 */
|
Chris@14
|
47 public function __construct(array $parameters)
|
Chris@14
|
48 {
|
Chris@14
|
49 foreach ($parameters as $parameter) {
|
Chris@14
|
50 if (!($parameter instanceof Constraint)) {
|
Chris@14
|
51 $parameter = new IsEqual(
|
Chris@14
|
52 $parameter
|
Chris@14
|
53 );
|
Chris@14
|
54 }
|
Chris@14
|
55
|
Chris@14
|
56 $this->parameters[] = $parameter;
|
Chris@14
|
57 }
|
Chris@14
|
58 }
|
Chris@14
|
59
|
Chris@14
|
60 /**
|
Chris@14
|
61 * @return string
|
Chris@14
|
62 */
|
Chris@14
|
63 public function toString()
|
Chris@14
|
64 {
|
Chris@14
|
65 $text = 'with parameter';
|
Chris@14
|
66
|
Chris@14
|
67 foreach ($this->parameters as $index => $parameter) {
|
Chris@14
|
68 if ($index > 0) {
|
Chris@14
|
69 $text .= ' and';
|
Chris@14
|
70 }
|
Chris@14
|
71
|
Chris@14
|
72 $text .= ' ' . $index . ' ' . $parameter->toString();
|
Chris@14
|
73 }
|
Chris@14
|
74
|
Chris@14
|
75 return $text;
|
Chris@14
|
76 }
|
Chris@14
|
77
|
Chris@14
|
78 /**
|
Chris@14
|
79 * @param BaseInvocation $invocation
|
Chris@14
|
80 *
|
Chris@14
|
81 * @return bool
|
Chris@14
|
82 *
|
Chris@14
|
83 * @throws \Exception
|
Chris@14
|
84 */
|
Chris@14
|
85 public function matches(BaseInvocation $invocation)
|
Chris@14
|
86 {
|
Chris@14
|
87 $this->invocation = $invocation;
|
Chris@14
|
88 $this->parameterVerificationResult = null;
|
Chris@14
|
89
|
Chris@14
|
90 try {
|
Chris@14
|
91 $this->parameterVerificationResult = $this->verify();
|
Chris@14
|
92
|
Chris@14
|
93 return $this->parameterVerificationResult;
|
Chris@14
|
94 } catch (ExpectationFailedException $e) {
|
Chris@14
|
95 $this->parameterVerificationResult = $e;
|
Chris@14
|
96
|
Chris@14
|
97 throw $this->parameterVerificationResult;
|
Chris@14
|
98 }
|
Chris@14
|
99 }
|
Chris@14
|
100
|
Chris@14
|
101 /**
|
Chris@14
|
102 * Checks if the invocation $invocation matches the current rules. If it
|
Chris@14
|
103 * does the matcher will get the invoked() method called which should check
|
Chris@14
|
104 * if an expectation is met.
|
Chris@14
|
105 *
|
Chris@14
|
106 * @return bool
|
Chris@14
|
107 *
|
Chris@14
|
108 * @throws ExpectationFailedException
|
Chris@14
|
109 */
|
Chris@14
|
110 public function verify()
|
Chris@14
|
111 {
|
Chris@14
|
112 if (isset($this->parameterVerificationResult)) {
|
Chris@14
|
113 return $this->guardAgainstDuplicateEvaluationOfParameterConstraints();
|
Chris@14
|
114 }
|
Chris@14
|
115
|
Chris@14
|
116 if ($this->invocation === null) {
|
Chris@14
|
117 throw new ExpectationFailedException('Mocked method does not exist.');
|
Chris@14
|
118 }
|
Chris@14
|
119
|
Chris@14
|
120 if (\count($this->invocation->getParameters()) < \count($this->parameters)) {
|
Chris@14
|
121 $message = 'Parameter count for invocation %s is too low.';
|
Chris@14
|
122
|
Chris@14
|
123 // The user called `->with($this->anything())`, but may have meant
|
Chris@14
|
124 // `->withAnyParameters()`.
|
Chris@14
|
125 //
|
Chris@14
|
126 // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199
|
Chris@14
|
127 if (\count($this->parameters) === 1 &&
|
Chris@14
|
128 \get_class($this->parameters[0]) === IsAnything::class) {
|
Chris@14
|
129 $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead.";
|
Chris@14
|
130 }
|
Chris@14
|
131
|
Chris@14
|
132 throw new ExpectationFailedException(
|
Chris@14
|
133 \sprintf($message, $this->invocation->toString())
|
Chris@14
|
134 );
|
Chris@14
|
135 }
|
Chris@14
|
136
|
Chris@14
|
137 foreach ($this->parameters as $i => $parameter) {
|
Chris@14
|
138 $parameter->evaluate(
|
Chris@14
|
139 $this->invocation->getParameters()[$i],
|
Chris@14
|
140 \sprintf(
|
Chris@14
|
141 'Parameter %s for invocation %s does not match expected ' .
|
Chris@14
|
142 'value.',
|
Chris@14
|
143 $i,
|
Chris@14
|
144 $this->invocation->toString()
|
Chris@14
|
145 )
|
Chris@14
|
146 );
|
Chris@14
|
147 }
|
Chris@14
|
148
|
Chris@14
|
149 return true;
|
Chris@14
|
150 }
|
Chris@14
|
151
|
Chris@14
|
152 /**
|
Chris@14
|
153 * @return bool
|
Chris@14
|
154 *
|
Chris@14
|
155 * @throws ExpectationFailedException
|
Chris@14
|
156 */
|
Chris@14
|
157 private function guardAgainstDuplicateEvaluationOfParameterConstraints()
|
Chris@14
|
158 {
|
Chris@14
|
159 if ($this->parameterVerificationResult instanceof \Exception) {
|
Chris@14
|
160 throw $this->parameterVerificationResult;
|
Chris@14
|
161 }
|
Chris@14
|
162
|
Chris@14
|
163 return (bool) $this->parameterVerificationResult;
|
Chris@14
|
164 }
|
Chris@14
|
165 }
|