在PHPUnit中,如何期望精确的模拟作为方法调用的参数,而不是同一类的任何模拟?

时间:2018-12-28 20:48:48

标签: php mocking phpunit

在下面的示例中(使用PHP 7.3和PHPUnit 7.5.1),我有两个相同类的模拟。我希望可以将两个模拟之一作为方法调用中的参数。但是,如果我用其他模拟程序调用该方法,期望值似乎就可以满足。

<?php declare(strict_types=1);

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    public function testExample()
    {
        $mock1 = $this->getMockBuilder(stdClass::class)->getMock();
        $mock2 = $this->getMockBuilder(stdClass::class)->getMock();
        /** @var MockObject|ArrayObject $mock3 */
        $mock3 = $this->getMockBuilder(ArrayObject::class)->setMethods(['append'])->getMock();

        $this->assertEquals($mock1, $mock2); // OK
        $this->assertNotSame($mock1, $mock2); // OK

        $mock3->expects($this->once())->method('append')->with($mock1); // OK

        // However I pass $mock2 instead of $mock1 !
        $mock3->append($mock2);

        // I would need something like :
        // $mock3->expects($this->once())->method('append')->withSameAs($mock1); // Not OK
    }
}

1 个答案:

答案 0 :(得分:1)

我认为您想要的是在$this->identicalTo函数中调用with函数。这将验证是否传递了正确的对象。如果您更新代码以传递$mock1,则该代码将失败,因为对象不相同

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

    class ExampleTest extends TestCase
    {
        public function testExample()
        {
            $mock1 = $this->getMockBuilder(stdClass::class)->getMock();
            $mock2 = $this->getMockBuilder(stdClass::class)->getMock();
            /** @var MockObject|ArrayObject $mock3 */
            $mock3 = $this->getMockBuilder(ArrayObject::class)
                ->setMethods(['append'])->getMock();

            $mock3->expects($this->once())->method('append')->with($this->identicalTo($mock2)); // OK
            $mock3->append($mock2);

        }
    }

其他示例:

use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    public function testExample()
    {
        $mock1 = $this->getMockBuilder(stdClass::class)->getMock();
        $mock2 = $this->getMockBuilder(stdClass::class)->getMock();
        /** @var MockObject|ArrayObject $mock3 */
        $mock3 = $this->getMockBuilder(ArrayObject::class)
            ->setMethods(['append'])->getMock();  

        $class = new ExampleClass($mock3);
        $mock3->expects($this->once())->method('append')->with($this->identicalTo($mock2)); // OK
        $class->appendObject($mock2);

    }
}

class ExampleClass
{
    private $array;

    public function __construct(ArrayObject $array)
    {
        $this->array = $array;
    }

    public function appendObject($stdClass)
    {
        $this->array->append($stdClass);
    }
}