Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

a-dev-coder-f's avatar

Mock Static Function (find) of Model Book and return Same Model Book

I'm trying to mock the find static function in my eloquent model and return a mocked model back.

class Book extends Model {}
        $bookMock = Mockery::mock(Book::class)->makePartial();
        Mockery::mock('alias:' . Book::class)
            ->makePartial()
            ->shouldReceive('find')
            ->with(1)
            ->andReturn($bookMock);

However, this will fail with an error

Mockery\Exception\RuntimeException: Could not load mock ..., class already exists 

This must be done in a single test, so running in different processes won't work.

How can I mock a static find function of eloquent model and return back a mocked model to use in the test?

0 likes
4 replies
a-dev-coder-f's avatar

This is called inside a function so I cannot return any random value and then use the real Book model afterwards.

martinbean's avatar

@a-dev-coder-f Why are you trying to mock Eloquent? It’s not your code; it will already be tested by the Laravel framework itself.

It might help if you showed why you were trying to mock the model, i.e. where you’re trying to use it and what you’re actually trying to test.

a-dev-coder-f's avatar

@martinbean I am testing a if flow path and this is the minimise reproducable behaviour to get to that, specifically where I'm stuck on.

// getBookDataFromFile

if ($order->bookID !== 0)
	$book = Book::find($order->bookID);

	return BookService::getBookData($book);

Since this code is called inside the function, I need to mock it to return a book model, but, as the question was about, you cannot mock alias and mock a class at the same time, there's a class already loaded error.

I'm not trying to test the eloquent, I'm trying to mock and return results so I don't need to create a eloquent model in the database that satisfies the query. Though, I think I have to, as I don't see any other way.

martinbean's avatar

@a-dev-coder-f You’re mocking the completely wrong thing. You should be mocking your BookService in tests that require it, where you don‘t want to test the service itself:

public function test_can_view_book(): void
{
    $book = Book::factory()->createOne();

    $this->mock(BookService::class, function () use ($book) {
        $mock->shouldReceive('getBookData')->once()->with(1)->andReturn($book);
    });

    // Test controller without service fetching anything from database...
    $this
        ->get('/books/1')
        ->assertOk()
        ->assertViewIs('book.show')
        ->assertViewHas('book', $book);
}
1 like

Please or to participate in this conversation.