sebastianbergmann/phpunit · error · ComparisonMethodDoesNotDeclareParameterTypeException
Parameter of comparison method %s::%s() does not have a decl
Error message
Parameter of comparison method %s::%s() does not have a declared type.
What it means
The single parameter of the comparison method used by assertObjectEquals() must have a declared type, so PHPUnit can verify the expected object is acceptable before invoking it. This variant is thrown when ReflectionParameter::hasType() is false, i.e. the parameter is untyped.
Source
Thrown at src/Framework/Constraint/Object/ObjectEquals.php:124
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) {
throw new ComparisonMethodDoesNotDeclareParameterTypeException(
$other::class,
$this->method,
);
}
$typeName = $type->getName();
if ($typeName === 'self') {
// @codeCoverageIgnoreStartView on GitHub (pinned to f123cdb2a2)
Solutions
- Add a parameter type, ideally `self` or the concrete class: `public function equals(self $other): bool`
- If the method genuinely accepts any object, declare it explicitly: `public function equals(mixed $other): bool` — 'mixed' is a declared type and passes this check
- Note: with a wide type you may then hit the instanceof acceptance check; prefer self or the specific value class
Example fix
// before
class Sku
{
public function equals($other): bool
{
return $other instanceof self && $this->code === $other->code;
}
}
// after
class Sku
{
public function equals(self $other): bool
{
return $this->code === $other->code;
}
} Defensive patterns
Strategy: type-guard
Type guard
function comparisonMethodParameterIsTyped(object $actual, string $method = 'equals'): bool
{
$params = (new ReflectionObject($actual))->getMethod($method)->getParameters();
return isset($params[0]) && $params[0]->hasType();
} Prevention
- Always declare the parameter type, ideally `self` or the concrete value class
- Explicit `mixed` counts as a type, but a self-typed parameter gives better safety and clearer failures
When it happens
Trigger: equals() declared as `public function equals($other): bool` — the parameter has no type declaration, often because it was written to accept anything (Java `Object $other` style) or predates PHP 7 type hints.
Common situations: Legacy equals(mixed $other) implementations (here 'mixed' as an explicit declared type would be fine, absence of any hint is not); code style guides that banned parameter types; docblock-typed but not natively typed parameters.
Related errors
- Comparison method %s::%s() does not exist.
- Comparison method %s::%s() does not declare bool return type
- Comparison method %s::%s() does not declare exactly one para
- %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/4e970cbe3147b2d4.
Report an issue: GitHub.