Search code examples
phpphpunitmockery

Set object set by code in Mockery


I've following code to be tested.

// $generator, $locale, $site are parameters.
// It is just a part of real code.
$text = new Text();
$text->setType($generator->getType())
    ->setLocale($locale)
    ->setSite($site->getId());

/** @var $site \namespace\Site */
$site->addText($text);

To test this, I'm making mock of Site using Mockery.

In test, I generally want to do

$text = $site->getText();
$this->assertInstanceOF('\namespace\Text', $text);
$this->assertSame($generator->getType(), $text->getType());
$this->assertSame($locale, $text->getLocale());
$this->assertSame($site->getId(), $text->getSite());

While making mock, I want mock to return the instance of Text created by original code and set in line $site->addText($site). I tried

$text = new Text();
$site = Mockery::mock(Site::class)
    ->shouldReceive('addText')
    ->with($text)
    ->andReturnUsing(function() {
            $args = func_get_args();
            return $args[0];
        })
    ->getMock();

This return me object of Text set in mocking code. In mockery, is there any way I can get Text object created in original code?


Solution

  • You can use the Mockery::on() method in this case. Refer to the argument validation docs . Here you can pass a closure which receives the argument passed to the addText method. You can also use PHPUnit assertions in this closure to do assertions on the $text parameter. Like this:

    $site = Mockery::mock(Site::class)
        ->shouldReceive('addText')
        ->with(Mockery::on(function($text) {
            $this->assertInstanceOF('\namespace\Text', $text);
            //More assertions
    
            return true; //You must return true, otherwise the expectation will never pass regardless of the assertions above.
        }));