{"record":{"id":"f241b376afcd5066","repo":"sebastianbergmann/phpunit","slug":"s-is-not-an-accepted-argument-type-for-comparison","errorCode":null,"errorMessage":"%s is not an accepted argument type for comparison method %s::%s().","messagePattern":"(.+?) is not an accepted argument type for comparison method (.+?)::(.+?)\\(\\)\\.","errorType":"exception","errorClass":"ComparisonMethodDoesNotAcceptParameterTypeException","httpStatus":null,"severity":"error","filePath":"src/Framework/Constraint/Object/ObjectEquals.php","lineNumber":148,"sourceCode":"        $type = $parameter->getType();\n\n        if (!$type instanceof ReflectionNamedType) {\n            throw new ComparisonMethodDoesNotDeclareParameterTypeException(\n                $other::class,\n                $this->method,\n            );\n        }\n\n        $typeName = $type->getName();\n\n        if ($typeName === 'self') {\n            // @codeCoverageIgnoreStart\n            $typeName = $other::class;\n            // @codeCoverageIgnoreEnd\n        }\n\n        if (!$this->expected instanceof $typeName) {\n            throw new ComparisonMethodDoesNotAcceptParameterTypeException(\n                $other::class,\n                $this->method,\n                $this->expected::class,\n            );\n        }\n\n        /** @phpstan-ignore method.dynamicName */\n        $result = $other->{$this->method}($this->expected);\n\n        assert(is_bool($result));\n\n        return $result;\n    }\n\n    protected function failureDescription(mixed $other): string\n    {\n        return $this->toString();\n    }","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/Constraint/Object/ObjectEquals.php#L130-L166","documentation":"The final precondition of assertObjectEquals(): PHPUnit takes the declared parameter type of the comparison method (resolving 'self' to the actual class) and requires the EXPECTED object passed to the assertion to be an instance of it, since it will be passed as the argument. If the expected object's class does not satisfy the parameter type, this exception is thrown instead of a type error at call time.","triggerScenarios":"assertObjectEquals($expected, $actual) where $actual's equals() accepts self/SomeClass but $expected is of a different class — e.g. expected is a parent class instance, a sibling subclass, a mock/stub, or an entirely different DTO that happens to be structurally equal.","commonSituations":"Comparing a base-class fixture against a subclass actual; comparing a named vs anonymous/other-library representation of the same value; expected value replaced with a PHPUnit mock or prophecy stub of an unrelated interface; typo passing arguments swapped (expected/actual of different types).","solutions":["Make the expected object an instance of the type the comparison method accepts (usually the same class as actual): build the fixture with the same class","If cross-class comparison is intended, widen the parameter type on equals() to a shared interface and ensure the expected object implements it","Check you have not swapped the arguments: assertObjectEquals($expected, $actual, ...)"],"exampleFix":"// before\n$expected = new BaseMoney(500, 'EUR');   // BaseMoney\n$actual   = new PaidMoney(500, 'EUR');    // subclass, equals(PaidMoney $other)\n$this->assertObjectEquals($expected, $actual);\n\n// after\n$expected = new PaidMoney(500, 'EUR');\n$actual   = new PaidMoney(500, 'EUR');\n$this->assertObjectEquals($expected, $actual);","handlingStrategy":"validation","validationCode":"// Ensure the expected object satisfies the comparator's parameter type BEFORE asserting:\n$param   = (new ReflectionObject($actual))->getMethod('equals')->getParameters()[0];\n$type    = $param->getType()->getName();\n$type    = $type === 'self' ? $actual::class : $type;\n\nif (!$expected instanceof $type) {\n    $this->markTestIncomplete(\n        sprintf('Expected must be %s, got %s', $type, $expected::class)\n    );\n}\n$this->assertObjectEquals($expected, $actual);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build the expected fixture from the same class (or subclass) as the actual value","Keep argument order consistent: assertObjectEquals($expected, $actual, $method)"],"tags":["php","phpunit","assertobjectequals","type-mismatch","equals-method"],"backgroundTag":"equals-method-contract-violation","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}