Search code examples
phplaravelphpunitlaravel-8mockery

Laravel: Test not Using Mocked Method


I want getNumber to return 200 in the test case, but when I run the test and inspect the result with $response->dump() I can see that the mock is not overriding the method as it is showing array:1 [0 => 100]. What am I missing?

Controller:

class ServiceController extends Controller
{
    public function fetch(Request $request)
    {
        $service = new Service();
    
        return [$service->getNumber()];
    }
}

Model:

class Service extends Model
{
    public function getNumber(): int
    {
        return 100;
    }
}

Test:

class ControllerTest extends TestCase
{
    public function testFetchGetsNumber()
    {
        $mock = $this->partialMock(Service::class, function (MockInterface $mock) {
            $mock->shouldReceive('getNumber')->andReturn(200);
        });
    
        $response = $this->post('/api/controller');
        $response->dump(); // returns 100 but should return 200...
    }
}

I am using Laravel 8 and referencing this documentation: https://laravel.com/docs/8.x/mocking#mocking-objects


Solution

  • In Laravel you have to use the container to mock classes.

    $service = resolve(Service::class);
    

    In constructors or handle methods, if you inject your classes there it will automatically use the container. If put into constructors or classes, remember the resolution of the class with the constructor, have to use the container.

    class Job 
    {
        public function handle(Service $service)
        {
            // will use the mocked service.
        }
    }