Search code examples
laravelphpunitphp-8php-pest

Argument #1 must be of type Model, Pest\Mock\Mock given


I'm trying to write some tests using Pest and mocking my model. I have a Repository that accepts two models, this is the definition:

class MyRepo
{
    public function __construct(private ModelA $modelA, private ModelB $modelB)
    {
      //
    }
}

Now in my test i created two mock for ModelA and ModelB, and created the repository:

$modelA = mock(ModelA::class);
$modelB = mock(ModelB::class);

$repo = new MyRepo($modelA, $modelB);

Running this code I get a check error like this:

__construct(): Argument #1 ($modelA) must be of type App\Models\ModelA, Pest\Mock\Mock given

If I remove the type check on Repository constructor, all works fine.

I tried to find a solution, but for now, I have had no luck. I'm not able to understand what i need to change to make it works


Solution

  • As the comment states, don't mock models, this is not the intended use of the testing tools in Laravel. In other words, i have written thousands of tests and not once i had to mock the model.

    Having Models as parameters to a constructor, wouldn't make sense. As Laravels container would often just resolve them to empty models, with resolve(MyRepo::class); and the container is an essential tool for Mocking.

    With that said, the problem you are facing is, mock() returns the Pest Mock object and not the Mockery object, this object is located here on the Pest Mock Class. This can only be returned by calling expect(). Therefor utilize expect(), with the operations you need to call on your mock and your code should work.

    mock(ModelA::class)
        ->shouldReceive('update')
        ->once()
        ->andReturn(true);