Search code examples
laravelphpunitmockery

How to mock only one method with Laravel using PhpUnit


I have this test :

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Services\AccessTokenService;
use App\Services\MemberService;

class BranchTest extends TestCase    

public function testPostBranchWithoutErrors()
    {
        $this->mock(AccessTokenService::class, function ($mock) {
            $mock->shouldReceive('introspectToken')->andReturn('introspection OK');
        });

        $this->mock(MemberService::class, function ($mock) {
            $mock->shouldReceive('getMemberRolesFromLdap')->andReturn(self::MOCKED_ROLES);
        });

As you see, there are 2 mocks on this test. The 2nd one 'MemberService:class' is my current problem. In this class there are 2 functions : 'createMember' and 'getMemberRolesFromLdap'. I precise that I want to mock only the 'getMemberRolesFromLdap' function.

In the documentation, it is written :

You may use the partialMock method when you only need to mock a few methods of an object. The methods that are not mocked will be executed normally when called:

$this->partialMock(Service::class, function ($mock) { $mock->shouldReceive('process')->once(); });

But when I use "partialMock", I have this error:

Error: Call to undefined method Tests\Feature\BranchTest::partialMock()

And when I try a classic mock (no partial), I have this error:

Received Mockery_1_App_Services_MemberService::createMember(), but no expectations were specified

certainly because there are 2 functions in this class and so PhpUnit does not know what to do with the function 'createMember'.

What can I try next? I am a beginner to PhpUnit tests.

Edit

Laravel 6.0
PhpUnit 7.5


Solution

  • PartialMock shorthand is firstly added in Laravel 6.2 see the release notes. So an upgrade to 6.2 should fix your problem.

    Secondly you can add the following snippet to your Tests\TestCase.php class and it should work.

    protected function partialMock($abstract, Closure $mock = null)
    {
        return $this->instance($abstract, Mockery::mock(...array_filter(func_get_args()))->makePartial());
    }
    

    With the upgrade, something like this should enable you to mock a single function.

    $mock = $this->partialMock(AccessTokenService::class, function (MockInterface $mock) {
        $mock->shouldReceive('introspectToken')->andReturn('introspection OK');
    });