1

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Toms Bugna
  • 502
  • 2
  • 10
  • 30
  • _"Laravel's automatic dependency resolving skips the __construct execution."_ I don't see why this would the case as laravel's IoC internally calls `new` when injecting dependencies can you show the implementation of `AnotherService` – Vinay Mar 05 '20 at 16:13
  • I updated my question. Please, check it again for more details. – Toms Bugna Mar 06 '20 at 08:39
  • 1
    Did you ever solve this? I am seeing similar behaviour, using `resolve()` the constructor of my service does not seem to be executed. – Don't Panic Feb 12 '21 at 08:15

1 Answers1

0

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Amega
  • 128
  • 6