sebastianbergmann/phpunit · error · ComparisonMethodDoesNotExistException
Comparison method %s::%s() does not exist.
Error message
Comparison method %s::%s() does not exist.
What it means
PHPUnit's assertObjectEquals() does not compare objects itself; it delegates to a user-defined comparison method on the actual object (default name 'equals'). Before calling it, the ObjectEquals constraint reflects on the actual object's class and requires the configured method to exist. If ReflectionObject::hasMethod() fails, this exception is thrown, meaning the actual value's class has no equals() (or custom-named) method.
Source
Thrown at src/Framework/Constraint/Object/ObjectEquals.php:75
/**
* @throws ActualValueIsNotAnObjectException
* @throws ComparisonMethodDoesNotAcceptParameterTypeException
* @throws ComparisonMethodDoesNotDeclareBoolReturnTypeException
* @throws ComparisonMethodDoesNotDeclareExactlyOneParameterException
* @throws ComparisonMethodDoesNotDeclareParameterTypeException
* @throws ComparisonMethodDoesNotExistException
*/
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(View on GitHub (pinned to f123cdb2a2)
Solutions
- Add a public instance method named equals (or the name passed as 3rd argument) to the actual object's class: `public function equals(self $other): bool`
- If your method has a different name (e.g. isEqualTo), pass it explicitly: assertObjectEquals($expected, $actual, 'isEqualTo')
- If you cannot modify the class, fall back to assertEquals($expected, $actual) which compares structurally without a custom method
Example fix
// before
$this->assertObjectEquals($expectedMoney, $actualMoney);
// RuntimeException-ish failure: Comparison method Money::equals() does not exist.
class Money { /* no equals() */ }
// after
class Money
{
public function equals(self $other): bool
{
return $this->amount === $other->amount && $this->currency === $other->currency;
}
}
$this->assertObjectEquals($expectedMoney, $actualMoney); Defensive patterns
Strategy: type-guard
Type guard
function hasComparisonMethod(object $actual, string $method = 'equals'): bool
{
return (new ReflectionObject($actual))->hasMethod($method);
}
if (!hasComparisonMethod($actual, 'equals')) {
$this->markTestIncomplete(get_class($actual) . ' has no equals() method');
} Try / catch
use PHPUnit\Framework\ComparisonMethodDoesNotExistException;
try {
$this->assertObjectEquals($expected, $actual);
} catch (ComparisonMethodDoesNotExistException $e) {
// authoring error: fix the class, do not swallow
$this->fail('Comparison method missing: ' . $e->getMessage());
} Prevention
- Pair assertObjectEquals() with a dedicated self-typed equals(): `public function equals(self $other): bool`
- Add a static-analysis/phpstan rule or architecture test that value objects used with assertObjectEquals declare equals()
When it happens
Trigger: assertObjectEquals($expected, $actual) where $actual's class declares no public equals() method; or assertObjectEquals($expected, $actual, 'isEqualTo') where 'isEqualTo' does not exist on the actual class (typo, or method only exists on the expected class, or it is defined on a parent the actual object does not extend).
Common situations: Value objects that only implement a static equals() or an isEqualTo() with a different name; test authors assuming assertObjectEquals works like assertEquals and skipping the equals() method; the method exists but on the expected object's class instead of the actual one; PHP 8 constructor-promoted DTOs where equals() was never written.
Related errors
- Comparison method %s::%s() does not declare bool return type
- Comparison method %s::%s() does not declare exactly one para
- Parameter of comparison method %s::%s() does not have a decl
- %s is not an accepted argument type for comparison method %s
- Configured code coverage driver class "%s" is not instantiab
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/cc683cc5eac39c3a.
Report an issue: GitHub.