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) TestsUnitServicesStageServiceTest::update_stage MockeryExceptionNoMatchingExpectationException: No matching handler found for Mockery_13_App_Entities_Subcategory::setAttribute('stage_updated_at', object(CarbonCarbon)). 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();
Advertisement
Answer
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');