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:
JavaScriptWhen 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');