sebastianbergmann/phpunit · error · ComparisonMethodDoesNotDeclareBoolReturnTypeException

Comparison method %s::%s() does not declare bool return type

Error message

Comparison method %s::%s() does not declare bool return type.

What it means

For assertObjectEquals(), PHPUnit requires the comparison method on the actual object to declare an explicit bool return type, because the constraint's return value drives pass/fail. This variant is thrown when ReflectionMethod::hasReturnType() is false, i.e. the method exists but has no return type at all.

Source

Thrown at src/Framework/Constraint/Object/ObjectEquals.php:84

    protected function matches(mixed $other): bool
    {
        if (!is_object($other)) {
            throw new ActualValueIsNotAnObjectException;
        }

        $object = new ReflectionObject($other);

        if (!$object->hasMethod($this->method)) {
            throw new ComparisonMethodDoesNotExistException(
                $other::class,
                $this->method,
            );
        }

        $method = $object->getMethod($this->method);

        if (!$method->hasReturnType()) {
            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
                $other::class,
                $this->method,
            );
        }

        $returnType = $method->getReturnType();

        if (!$returnType instanceof ReflectionNamedType) {
            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
                $other::class,
                $this->method,
            );
        }

        if ($returnType->allowsNull()) {
            throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
                $other::class,
                $this->method,

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Add the bool return type to the comparison method: `public function equals(self $other): bool`
  2. If you cannot change the class, use assertEquals() instead of assertObjectEquals()

Example fix

// before
class Email
{
    public function equals(self $other) // no return type
    {
        return $this->value === $other->value;
    }
}

// after
class Email
{
    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }
}
Defensive patterns

Strategy: type-guard

Type guard

function comparisonMethodHasReturnType(object $actual, string $method = 'equals'): bool
{
    $m = (new ReflectionObject($actual))->getMethod($method);
    return $m->hasReturnType()
        && $m->getReturnType() instanceof \ReflectionNamedType
        && $m->getReturnType()->getName() === 'bool'
        && !$m->getReturnType()->allowsNull();
}

if (!comparisonMethodHasReturnType($actual)) {
    $this->markTestIncomplete('equals() must declare `: bool`');
}

Prevention

When it happens

Trigger: assertObjectEquals($expected, $actual) where the actual class's equals() (or custom-named method) is declared without a return type, e.g. `public function equals($other)` or `public function equals(self $other) { ... }` with no `: bool`.

Common situations: Legacy pre-PHP-7.4 codebases where return types were not used; equals() methods ported from Java that return bool but never declared the type; generated code or DTO builders that omit return types; teams adding assertObjectEquals() to an existing untyped codebase.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/fd4b6277fb4803b8. Report an issue: GitHub.