[PHPUnit]Failed asserting that two variables reference the same object.

はじめに
---
オブジェクト指向を学び初めたばかりです。
オブジェクトが絡むエラーがいまいち理解できなかったので記事にしました。


やりたいこと
---
assertSameメソッドのexpectedもactualも同じオブジェクトnew Card('クラブ', '10') なのにエラーになる。それを解消したい。

```php
//$dealer->hands->getFirstCard());をすると
//new Card('クラブ', '10')が取得できていることをテストしたい

//テストコード

public function testGetFirstCard()
    {
        $dealer = new Dealer('ディーラー');
        $dealer->hands->cards = [new Card('クラブ', '10'), new Card('クラブ', 'A')];
        $this->assertSame(new Card('クラブ', '10'), $dealer->hands->getFirstCard());
    }

//$dealer->hands->getFirstCard()で$dealer->hands->cardsプロパティのnew Card('クラブ', '10')を取得している

```

やったこと/解決策
---
そもそも「$cardsプロパティの0番目のnew Card('クラブ', '10')が取得できているか」を確認したいテスト

なので、期待値に「new Card('クラブ', '10')」を定義するのではなく、「$cardsプロパティのnew Card('クラブ', '10')」にアクセスするように修正した。<font color='red'>⇒ passした</font>

```php

public function testGetFirstCard()
    {
        $dealer = new Dealer('ディーラー');
        $dealer->hands->cards = [new Card('クラブ', '10'), new Card('クラブ', 'A')];
        $this->assertSame($dealer->hands->cards[0], $dealer->hands->getFirstCard());
    }
//$dealer->hands->cards[0]で「$cardsプロパティのnew Card('クラブ', '10')」にアクセス

```

原因
---
このエラーメッセージは、expectedとactualのオブジェクトが同じオブジェクトを<font color='red'>**参照していること**</font>を期待するアサーションで失敗したことを示していた。

<font color='red'>どちらもnew Card('クラブ', '10')ですが、expectedとactualで参照している先が異なっていた。</font>

```php
//$cardsプロパティ
$dealer->hands->cards = [new Card('クラブ', '10'), new Card('クラブ', 'A')];

//両方とも$cardsプロパティのnew Card('クラブ', '10')を取得
$dealer->hands->getFirstCard()
$dealer->hands->cards[0]

//[NG]ここのexpectedのnew Card('クラブ', '10')は「ただのnew Card('クラブ', '10')」
$this->assertSame(new Card('クラブ', '10'), $dealer->hands->getFirstCard());

//[OK]ここのexpectedのnew Card('クラブ', '10')は「$cardsプロパティのnew Card('クラブ', '10')」
$this->assertSame($dealer->hands->cards[0], $dealer->hands->getFirstCard());
```

expectedもactualと全く同じオブジェクトを参照する必要があるため、$cardsプロパティのnew Card('クラブ', '10')オブジェクトにアクセスしないといけなかった。



参考
---
**chatGPT**

このエラーメッセージは、2つのオブジェクトが同じオブジェクトを参照していることを期待するアサーションで失敗したことを示しています。つまり、2つの変数が異なるインスタンスを参照しているため、アサーションによってエラーが発生しました。

この問題を解決するには、テスト内で2つの変数が同じインスタンスを参照するように確認する必要があります。

**PHPUnitドキュメント**
全く同じオブジェクトを参照する必要がありと記載
[https://docs.phpunit.de/en/10.1/assertions.html?highlight=Failed asserting that two variables reference the same object.#assertsame](https://docs.phpunit.de/en/10.1/assertions.html?highlight=Failed%20asserting%20that%20two%20variables%20reference%20the%20same%20object.#assertsame)

>Reports an error identified by $message if the two variables expected and actual do not reference the same object.



```php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class SameWithObjectsTest extends TestCase
{
    public function testFailure(): void
    {
        $this->assertSame(new stdClass, new stdClass);
    }
}

// There was 1 failure:

// 1) SameWithObjectsTest::testFailure
// Failed asserting that two variables reference the same object.
```

**stuck overflow**
2つのオブジェクトが同じオブジェクトインスタンスを参照している場合にのみ、Passする。したがって、2つの別々のオブジェクトがすべての属性でまったく同じ値を持つ場合でも、同じインスタンスを参照していなければassertSame()は失敗します。
>When it comes to objects comparison:
assertSame
Can only assert if two objects are referencing the same object instance. So even if two separate objects have for all of their attributes exactly the same values, assertSame() will fail if they don't reference the same instance.
```php
$expected = new \stdClass();
$expected->foo = 'foo';
$expected->bar = 'bar';

$actual = new \stdClass();
$actual->foo = 'foo';
$actual->bar = 'bar';

$this->assertSame($expected, $actual); // FAILS

```
補足〜assertSameとassertEqualsの違い
---
assertSameは厳密な比較が行われている（型、値、オブジェクトの場合は参照先も比較されている）
```php
assertSame('2204', 2204) // this test fails
```
assertEqualsは緩やかな比較が行われている
```php
assertEquals('2204', 2204) // this test passes
```

https://stackoverflow.com/questions/10254180/difference-between-assertequals-and-assertsame-in-phpunit


最後に
---
assertSameはなぜオブジェクトの参照先までチェックする？と追加で気になったので、いろいろググって見たけど理由は見つけられませんでした。
まあでも、記事に残すことが出来て理解も深まりスッキリしました＼(^o^)／