0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Posted at

はじめに

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

やりたいこと

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

//$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')」にアクセスするように修正した。⇒ passした


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のオブジェクトが同じオブジェクトを参照していることを期待するアサーションで失敗したことを示していた。

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

//$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

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

<?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.

$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は厳密な比較が行われている(型、値、オブジェクトの場合は参照先も比較されている)

assertSame('2204', 2204) // this test fails

assertEqualsは緩やかな比較が行われている

assertEquals('2204', 2204) // this test passes

最後に

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?