Skip to content

Commit 6099c5e

Browse files
Report an error instead of a failure when the prerequisites for using the custom comparison function are not met
1 parent 6f084fa commit 6099c5e

8 files changed

+301
-125
lines changed

src/Framework/Constraint/Object/ObjectEquals.php

Lines changed: 53 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111

1212
use function get_class;
1313
use function is_object;
14+
use PHPUnit\Framework\ActualValueIsNotAnObjectException;
15+
use PHPUnit\Framework\ComparisonMethodDoesNotAcceptParameterTypeException;
16+
use PHPUnit\Framework\ComparisonMethodDoesNotDeclareBoolReturnTypeException;
17+
use PHPUnit\Framework\ComparisonMethodDoesNotDeclareExactlyOneParameterException;
18+
use PHPUnit\Framework\ComparisonMethodDoesNotDeclareParameterTypeException;
19+
use PHPUnit\Framework\ComparisonMethodDoesNotExistException;
1420
use ReflectionNamedType;
1521
use ReflectionObject;
1622

@@ -19,20 +25,6 @@
1925
*/
2026
final class ObjectEquals extends Constraint
2127
{
22-
private const ACTUAL_IS_NOT_AN_OBJECT = 1;
23-
24-
private const ACTUAL_DOES_NOT_HAVE_METHOD = 2;
25-
26-
private const METHOD_DOES_NOT_HAVE_BOOL_RETURN_TYPE = 3;
27-
28-
private const METHOD_DOES_NOT_ACCEPT_EXACTLY_ONE_ARGUMENT = 4;
29-
30-
private const PARAMETER_DOES_NOT_HAVE_DECLARED_TYPE = 5;
31-
32-
private const EXPECTED_NOT_COMPATIBLE_WITH_PARAMETER_TYPE = 6;
33-
34-
private const OBJECTS_ARE_NOT_EQUAL_ACCORDING_TO_METHOD = 7;
35-
3628
/**
3729
* @var object
3830
*/
@@ -43,11 +35,6 @@ final class ObjectEquals extends Constraint
4335
*/
4436
private $method;
4537

46-
/**
47-
* @var int
48-
*/
49-
private $failureReason;
50-
5138
public function __construct(object $object, string $method = 'equals')
5239
{
5340
$this->expected = $object;
@@ -59,71 +46,85 @@ public function toString(): string
5946
return 'two objects are equal';
6047
}
6148

49+
/**
50+
* @throws ActualValueIsNotAnObjectException
51+
* @throws ComparisonMethodDoesNotExistException
52+
* @throws ComparisonMethodDoesNotDeclareBoolReturnTypeException
53+
* @throws ComparisonMethodDoesNotDeclareExactlyOneParameterException
54+
* @throws ComparisonMethodDoesNotDeclareParameterTypeException
55+
* @throws ComparisonMethodDoesNotAcceptParameterTypeException
56+
*/
6257
protected function matches($other): bool
6358
{
6459
if (!is_object($other)) {
65-
$this->failureReason = self::ACTUAL_IS_NOT_AN_OBJECT;
66-
67-
return false;
60+
throw new ActualValueIsNotAnObjectException;
6861
}
6962

7063
$object = new ReflectionObject($other);
7164

7265
if (!$object->hasMethod($this->method)) {
73-
$this->failureReason = self::ACTUAL_DOES_NOT_HAVE_METHOD;
74-
75-
return false;
66+
throw new ComparisonMethodDoesNotExistException(
67+
get_class($other),
68+
$this->method
69+
);
7670
}
7771

7872
/** @noinspection PhpUnhandledExceptionInspection */
7973
$method = $object->getMethod($this->method);
8074

8175
if (!$method->hasReturnType()) {
82-
$this->failureReason = self::METHOD_DOES_NOT_HAVE_BOOL_RETURN_TYPE;
83-
84-
return false;
76+
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
77+
get_class($other),
78+
$this->method
79+
);
8580
}
8681

8782
$returnType = $method->getReturnType();
8883

8984
if (!$returnType instanceof ReflectionNamedType) {
90-
$this->failureReason = self::METHOD_DOES_NOT_HAVE_BOOL_RETURN_TYPE;
91-
92-
return false;
85+
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
86+
get_class($other),
87+
$this->method
88+
);
9389
}
9490

9591
if ($returnType->allowsNull()) {
96-
$this->failureReason = self::METHOD_DOES_NOT_HAVE_BOOL_RETURN_TYPE;
97-
98-
return false;
92+
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
93+
get_class($other),
94+
$this->method
95+
);
9996
}
10097

10198
if ($returnType->getName() !== 'bool') {
102-
$this->failureReason = self::METHOD_DOES_NOT_HAVE_BOOL_RETURN_TYPE;
103-
104-
return false;
99+
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
100+
get_class($other),
101+
$this->method
102+
);
105103
}
106104

107105
if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) {
108-
$this->failureReason = self::METHOD_DOES_NOT_ACCEPT_EXACTLY_ONE_ARGUMENT;
109-
110-
return false;
106+
throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException(
107+
get_class($other),
108+
$this->method
109+
);
111110
}
112111

113112
$parameter = $method->getParameters()[0];
114113

115114
if (!$parameter->hasType()) {
116-
$this->failureReason = self::PARAMETER_DOES_NOT_HAVE_DECLARED_TYPE;
117-
118-
return false;
115+
throw new ComparisonMethodDoesNotDeclareParameterTypeException(
116+
get_class($other),
117+
$this->method
118+
);
119119
}
120120

121121
$type = $parameter->getType();
122122

123123
if (!$type instanceof ReflectionNamedType) {
124-
$this->failureReason = self::PARAMETER_DOES_NOT_HAVE_DECLARED_TYPE;
125-
126-
return false;
124+
throw new ComparisonMethodDoesNotDeclareParameterTypeException(
125+
get_class($other),
126+
$this->method
127+
);
127128
}
128129

129130
$typeName = $type->getName();
@@ -133,73 +134,18 @@ protected function matches($other): bool
133134
}
134135

135136
if (!$this->expected instanceof $typeName) {
136-
$this->failureReason = self::EXPECTED_NOT_COMPATIBLE_WITH_PARAMETER_TYPE;
137-
138-
return false;
137+
throw new ComparisonMethodDoesNotAcceptParameterTypeException(
138+
get_class($other),
139+
$this->method,
140+
get_class($this->expected)
141+
);
139142
}
140143

141-
if ($other->{$this->method}($this->expected)) {
142-
return true;
143-
}
144-
145-
$this->failureReason = self::OBJECTS_ARE_NOT_EQUAL_ACCORDING_TO_METHOD;
146-
147-
return false;
144+
return $other->{$this->method}($this->expected);
148145
}
149146

150147
protected function failureDescription($other): string
151148
{
152149
return $this->toString();
153150
}
154-
155-
protected function additionalFailureDescription($other): string
156-
{
157-
switch ($this->failureReason) {
158-
case self::ACTUAL_IS_NOT_AN_OBJECT:
159-
return 'Actual value is not an object.';
160-
161-
case self::ACTUAL_DOES_NOT_HAVE_METHOD:
162-
return sprintf(
163-
'%s::%s() does not exist.',
164-
get_class($other),
165-
$this->method
166-
);
167-
168-
case self::METHOD_DOES_NOT_HAVE_BOOL_RETURN_TYPE:
169-
return sprintf(
170-
'%s::%s() does not declare a bool return type.',
171-
get_class($other),
172-
$this->method
173-
);
174-
175-
case self::METHOD_DOES_NOT_ACCEPT_EXACTLY_ONE_ARGUMENT:
176-
return sprintf(
177-
'%s::%s() does not accept exactly one argument.',
178-
get_class($other),
179-
$this->method
180-
);
181-
182-
case self::PARAMETER_DOES_NOT_HAVE_DECLARED_TYPE:
183-
return sprintf(
184-
'Parameter of %s::%s() does not have a declared type.',
185-
get_class($other),
186-
$this->method
187-
);
188-
189-
case self::EXPECTED_NOT_COMPATIBLE_WITH_PARAMETER_TYPE:
190-
return sprintf(
191-
'%s is not accepted an accepted argument type for %s::%s().',
192-
get_class($this->expected),
193-
get_class($other),
194-
$this->method
195-
);
196-
197-
default:
198-
return sprintf(
199-
'The objects are not equal according to %s::%s().',
200-
get_class($other),
201-
$this->method
202-
);
203-
}
204-
}
205151
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Framework;
11+
12+
use const PHP_EOL;
13+
14+
/**
15+
* @internal This class is not covered by the backward compatibility promise for PHPUnit
16+
*/
17+
final class ActualValueIsNotAnObjectException extends Exception
18+
{
19+
public function __construct()
20+
{
21+
parent::__construct(
22+
'Actual value is not an object',
23+
0,
24+
null
25+
);
26+
}
27+
28+
public function __toString(): string
29+
{
30+
return $this->getMessage() . PHP_EOL;
31+
}
32+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Framework;
11+
12+
use const PHP_EOL;
13+
use function sprintf;
14+
15+
/**
16+
* @internal This class is not covered by the backward compatibility promise for PHPUnit
17+
*/
18+
final class ComparisonMethodDoesNotAcceptParameterTypeException extends Exception
19+
{
20+
public function __construct(string $className, string $methodName, string $type)
21+
{
22+
parent::__construct(
23+
sprintf(
24+
'%s is not an accepted argument type for comparison method %s::%s().',
25+
$type,
26+
$className,
27+
$methodName
28+
),
29+
0,
30+
null
31+
);
32+
}
33+
34+
public function __toString(): string
35+
{
36+
return $this->getMessage() . PHP_EOL;
37+
}
38+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Framework;
11+
12+
use const PHP_EOL;
13+
use function sprintf;
14+
15+
/**
16+
* @internal This class is not covered by the backward compatibility promise for PHPUnit
17+
*/
18+
final class ComparisonMethodDoesNotDeclareBoolReturnTypeException extends Exception
19+
{
20+
public function __construct(string $className, string $methodName)
21+
{
22+
parent::__construct(
23+
sprintf(
24+
'Comparison method %s::%s() does not declare bool return type.',
25+
$className,
26+
$methodName
27+
),
28+
0,
29+
null
30+
);
31+
}
32+
33+
public function __toString(): string
34+
{
35+
return $this->getMessage() . PHP_EOL;
36+
}
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Framework;
11+
12+
use const PHP_EOL;
13+
use function sprintf;
14+
15+
/**
16+
* @internal This class is not covered by the backward compatibility promise for PHPUnit
17+
*/
18+
final class ComparisonMethodDoesNotDeclareExactlyOneParameterException extends Exception
19+
{
20+
public function __construct(string $className, string $methodName)
21+
{
22+
parent::__construct(
23+
sprintf(
24+
'Comparison method %s::%s() does not declare exactly one parameter.',
25+
$className,
26+
$methodName
27+
),
28+
0,
29+
null
30+
);
31+
}
32+
33+
public function __toString(): string
34+
{
35+
return $this->getMessage() . PHP_EOL;
36+
}
37+
}

0 commit comments

Comments
 (0)