5

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();
Jeremy
  • 1,170
  • 9
  • 26

1 Answers1

4

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');
Philip Weinke
  • 1,804
  • 1
  • 8
  • 13
  • Sorry for the slow response, if i had hamcrest installed I think that your answer will solve the problem, I tried to implement, but i have not been able to get hamcrest working. Is there a solution that does not use hamcrest - or how would i call the hamcrest function? Thank you very much for your answer. – Jeremy Oct 30 '20 at 13:33
  • 2
    To use the global matcher functions like `equalTo`, you have to register them using `\Hamcrest\Util::registerGlobalFunctions();`. Alternatively, you could use `Hamcrest\Matchers::equalTo(Carbon::now())`. – Philip Weinke Oct 30 '20 at 13:42