Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Carbon object in mockery php test

Tags:

Thank you for your time. I have stripped out the fluff from the code/test.

The furthest I have got with this is that setAttribute requires two strings as param´s, but i am passing in an Carbon object, which Mockery as a test suite does not like? Is this the case, is there a better way to test dates with Mockery/PHPUnit? Other tests and code works, it seems like it´s only this test that is an issue.

Error

1) Tests\Unit\Services\StageServiceTest::update_stage
Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_13_App_Entities_Subcategory::setAttribute('stage_updated_at', object(Carbon\Carbon)). Either the method was unexpected or its arguments matched no expected argument list for this method

Objects: ( array (
  'Carbon\\Carbon' => 
  array (
    'class' => 'Carbon\\Carbon',
    'properties' => 
    array (
    ),
  ),
))

Bit of the test

        $subcategory = \Mockery::mock(Subcategory::class);
        $stage = \Mockery::mock(Stage::class);
        $subcategory
            ->shouldReceive('setAttribute')
            ->with('stage_updated_at', Carbon::now())
            ->once();
       $this->service->updateSubcategoryStage(self::SUBCATEGORY_ID, $stageId);

Bit of the code

        $subcategory->stage_updated_at = Carbon::now();
        $subcategory->save();
like image 338
Jeremy Avatar asked Oct 23 '20 12:10

Jeremy


1 Answers

It's not clear from your example who's calling setAttribute. But I guess that you are probably using magic setters.

The reason why your expectation is failing is because you are comparing two different objects. From the docs:

When matching objects as arguments, Mockery only does the strict === comparison, which means only the same $object will match

You can loosen the comparison by using the equalTo hamcrest matcher:

$subcategory
    ->shouldReceive('setAttribute')
    ->with('stage_updated_at', equalTo(Carbon::now()))
    ->once();

You will still get into trouble because the time will always be slightly off. Fortunately, Carbon provides a way to fix "now" for testing purposes. You just have to set it in your test case:

Carbon::setTestNow('2020-01-31 12:13:14');
like image 73
Philip Weinke Avatar answered Sep 29 '22 09:09

Philip Weinke