Toms Bugna
Toms Bugna

Reputation: 499

Laravel - resolve class with dependencies AND execute the constructor of instantiated class

Consider this code:

<?php namespace App\Services;

use App\Services\AnotherService;

class SomeService {
    public function someMethod() {
        $anotherService = \App::make(AnotherService::class);
    }
}

My intention is to get a class object with all its dependencies resolved. But in this specific case, I would like that the object's __construct has been executed as well. I have tried and by code above, the $anotherService object's __construct method is not executed.

Therefore I can achieve what I need by doing -

$anotherService = \App::make(AnotherService::class);
$anotherService->__construct();

Can it be done with single line instead of redundantly each time call construct method after instantiating the object? - Because that is what __construct method is made for - executing automatically. But I have noticed that for some reason Laravel's automatic dependency resolving skips the __construct execution.

Note, that new AnotherService() is not an option for me, as well as using the __construct method of SomeService class. I would like to make an object inside the someMethod method.

Class AnotherService currently does not have any dependencies. It has just some random variable updates inside the __construct, like:

public function __construct() {
    $this->varA = true;
    $this->varB = 'Some Value';
}

Why do I need to resolve this class (instead of using new AnotherClass())? - Simply because I want to test this call in unit tests by mocking it. For that I use this code:

$this->mock(AnotherService::class, function ($mock) {
    $mock->shouldReceive('anotherMethod')->andReturn(false);
});

And then finally I have to call the method to check the response:

$anotherService = \App::make(AnotherService::class);//<-- In this moment $varA and $varB are not set because the __construct did not execute!
$response = $anotherService->anotherMethod();

// Assert...

So, in this case, for example, if anotherMethod would use any of those variables, the tests would be incorrect because their values are not set.

Upvotes: 1

Views: 3179

Answers (1)

Amega
Amega

Reputation: 138

I believe there is either a mistake somewhere in your code or some misunderstanding.

The problem here is not in Laravel. The key here is the usage of Mockery. When creating a simple Mock for a class, its constructor is not invoked, and it's just a mock. When using $this->mock(...), you just bind a concrete instance (mock) in the container. Thus, when calling its make, that ready mock is returned. Meaning, that __construct is neither invoked by Mockery, nor by Container.

Upvotes: 0

Related Questions