#400·prophecy

Can't check for object identity with Argument::is() if they are weakly equal

Author: jnvsorCreated Apr 15, 2018Updated Oct 7, 2025

When mocking a method Argument::is can't be used to distinguish objects that are weakly identical.

Since identity is the whole point of Argument::is over Argument::exact for objects, this is rather annoying.

If I had to guess the source of the problem is in the assertEquals in ObjectProphecy::__call, since the additional prophecies aren't even registered.

Here's an example:

php
<?php

use Prophecy\Prophet;
use Prophecy\Argument;

require 'vendor/autoload.php';

$p = new Prophet();

$dt1 = new DateTime();
$dt2 = clone $dt1;
$dt3 = clone $dt1;

class TestClass {
    public function methodCall()
    {
    }
}

$prophecyObject = $p->prophesize('TestClass');

// Argument::exact doesn't work because the properties have the same values
$prophecyObject->methodCall(Argument::exact($dt1))->shouldBeCalledTimes(1);
$prophecyObject->methodCall(Argument::exact($dt2))->shouldBeCalledTimes(1);
$prophecyObject->methodCall(Argument::exact($dt3))->shouldBeCalledTimes(1);

// Argument::is doesn't work because for some reason it flat out refuses to
// store more than one IdenticalValueToken even when called repeatedly
$prophecyObject->methodCall(Argument::is($dt1))->shouldBeCalledTimes(1);
$prophecyObject->methodCall(Argument::is($dt2))->shouldBeCalledTimes(1);
$prophecyObject->methodCall(Argument::is($dt3))->shouldBeCalledTimes(1);

// My current workaround
$prophecyObject->methodCall(
    Argument::that(function ($arg) use ($dt1) {
        return $arg === $dt1;
    })
)->shouldBeCalledTimes(1);
$prophecyObject->methodCall(
    Argument::that(function ($arg) use ($dt2) {
        return $arg === $dt2;
    })
)->shouldBeCalledTimes(1);
$prophecyObject->methodCall(
    Argument::that(function ($arg) use ($dt3) {
        return $arg === $dt3;
    })
)->shouldBeCalledTimes(1);

$dummy = $prophecyObject->reveal();

$dummy->methodCall($dt1);
$dummy->methodCall($dt2);
$dummy->methodCall($dt3);

$p->checkPredictions();