user1392897
user1392897

Reputation: 851

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

Upvotes: 1

Views: 2003

Answers (2)

Paul Trimor
Paul Trimor

Reputation: 340

The issue is that your "Service" is not registered to the Service Container.

Inside AppServiceProvider.php make sure to registered the "service" you want to bind.

$this->instance->bind('service', ... );

In your Controller, instead of instantiating the class with the new keyword, use Laravel's app()->make('service').

This will allow you to Mock the class in your Unit Test. Inside your Test case..

 $this->app->bind('Service', $mock); 

Upvotes: 0

mrhn
mrhn

Reputation: 18916

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.
    }
}

Upvotes: 1

Related Questions