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

budiantoip's avatar

How to mock model's static function in phpunit?

I'm using laravel 4.2 and phpunit 5.7.

EventController@index :

public function index()
{
    $my_profile = View::shared('my_profile');

    $per_page = Input::get('per_page') ?: Config::get('pagination.custom')[0];

    $event_overviews = Event::getEventsAsOwnerAndTeamMemberByUserId($my_profile->userid)->paginate($per_page);

    return View::make('user/event.overview.index', compact('event_overviews'));
}

and here's my unit test :

public function loginWithFakeUser()
{
    $user = new User([
        'userid' => 1,
        'email'  => '[email protected]',
    ]);

    $this->be($user);

    return $user;
}

public function testEventIndex()
{

    $this->loginWithFakeUser();

    $event = $this->getMockBuilder(Event::class)
                        ->disableOriginalConstructor()
                        ->getMock();
    $event->expects($this->once())->method('getEventsAsOwnerAndTeamMemberByUserId');

    $this->app->instance('Event', $event);

    $this->call('GET', action('User\EventController@index'));

}

running the unit test returns this error message :

1) EventTest::testEventIndex
Trying to configure method "getEventsAsOwnerAndTeamMemberByUserId" which cannot be configured because it does not exist, has not been specified, is final, or is static

it must be because the function is static, but changing the way we call model's function will require lots of efforts, as lots of places are calling the model's function this way.

I wish there's a way, any clue on how to proceed will be much appreciated.

0 likes
5 replies
bobbybouwmann's avatar

Mmh, this is indeed hard to test. Mocking your models in is general hard to do and in my opinion a bad practise. If I'm looking at your code I see that you call some url that triggers a controller which returns a view. Why don't you test against that

public function testEventIndex()
{
    $this->loginWithFakeUser();

    $response = $this->call('GET', action('User\EventController@index'));

    $response->assertOk()
        ->assertViewIs('user/event.overview.index')
        ->assertViewHas('event_overviews');
}

You can find more like these methods here: https://laravel.com/docs/6.x/http-tests#available-assertions

Note: Testing should be fun and easy ;) Don't try to mock what you don't own like the way models work on Laravel :D

budiantoip's avatar

actually, the above unit test will be an example so I have an idea on how to mock objects on create, edit and delete functions. I'm mocking objects because I don't want to insert any dirty data into database.

goldtaste's avatar

I think it is generally very hard to mock static methods in phpunit. There is an article about it here: http://miljar.github.io/blog/2014/01/29/phpunit-testing-static-calls/. And it looks like a major hassle.

The best thing to do is to generally try and avoid static methods. Also, in an ideal scenario you would mock out objects that speak to the database. But you are using eloquent and doing both of those things really doesn't make sense. Just work with what you've got and unit test with the db involved.

As @bobbybouwmann mentions, you should set up a separate db for testing (in memory or sqlite, so it's faster) and you will be able to refresh it for each test.

1 like

Please or to participate in this conversation.