sebastianbergmann/phpunit · error · ComparisonMethodDoesNotDeclareExactlyOneParameterException
Comparison method %s::%s() does not declare exactly one para
Error message
Comparison method %s::%s() does not declare exactly one parameter.
What it means
The comparison method used by assertObjectEquals() must declare exactly one parameter, and that parameter must be required (no default). PHPUnit reflects the method and throws this exception when getNumberOfParameters() or getNumberOfRequiredParameters() differs from 1, because the constraint calls it as `$other->equals($expected)` with exactly one argument.
Source
Thrown at src/Framework/Constraint/Object/ObjectEquals.php:114
);
}
if ($returnType->allowsNull()) {
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
$other::class,
$this->method,
);
}
if ($returnType->getName() !== 'bool') {
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
$other::class,
$this->method,
);
}
if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) {
throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException(
$other::class,
$this->method,
);
}
assert(count($method->getParameters()) > 0);
$parameter = $method->getParameters()[0];
if (!$parameter->hasType()) {
throw new ComparisonMethodDoesNotDeclareParameterTypeException(
$other::class,
$this->method,
);
}
$type = $parameter->getType();
if (!$type instanceof ReflectionNamedType) {View on GitHub (pinned to f123cdb2a2)
Solutions
- Declare exactly one required typed parameter: `public function equals(self $other): bool`
- Move extra options into the method's behavior or separate methods (equalsStrict()) and pass that name to assertObjectEquals()
- If a no-arg comparator compares against an internal expected value, restructure the test to use assertThat($actual->value(), $this->equalTo($expectedValue))
Example fix
// before
class Money
{
public function equals(self $other = null, bool $strict = true): bool { ... }
}
$this->assertObjectEquals($expected, $actual);
// after
class Money
{
public function equals(self $other): bool { ... }
}
$this->assertObjectEquals($expected, $actual); Defensive patterns
Strategy: type-guard
Type guard
function comparisonMethodTakesExactlyOneRequiredParameter(object $actual, string $method = 'equals'): bool
{
$m = (new ReflectionObject($actual))->getMethod($method);
return $m->getNumberOfParameters() === 1
&& $m->getNumberOfRequiredParameters() === 1;
} Prevention
- Comparator signature is fixed: exactly one required parameter — no defaults, no variadics, no extra flags
- Move strictness/strategy options into separate method names (equalsStrict()) passed to assertObjectEquals()
When it happens
Trigger: equals() declared with zero parameters (`public function equals(): bool`), with two or more parameters, or with one optional parameter having a default value (`public function equals(self $other = null): bool`); also variadic signatures `equals(self ...$others)`.
Common situations: Java-ported equals(mixed $other = null) with a nullable default; 'fluent' comparison APIs like equals($other, $strict = true); stateless helpers that compare against an injected field and take no argument.
Related errors
- Comparison method %s::%s() does not exist.
- Comparison method %s::%s() does not declare bool return type
- Parameter of comparison method %s::%s() does not have a decl
- %s is not an accepted argument type for comparison method %s
- Subscriber "%s" does not implement any known interface - did
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/77df551eb57f980e.
Report an issue: GitHub.