0

I'm using Dependency injection to call custom services in Laravel and it works fine. But when i inject those dependencies into my Phpunit test case classes using interfaces, i receive the following error:

Target [App\Services\Interfaces\CarServiceInterface] is not instantiable.

although the interface has been bound to the target concrete class in the provider correctly.
i've used different styles like injecting through the __construct() method, inject to test method or even calling the app() method, but none of them works.

The test file:

private $carService;

public function setUp(): void
{
    parent::setUp();

    $this->carService = app(CarServiceInterface::class);
}

The provider:

$this->app->bind(
    App\Services\Interfaces\CarServiceInterface::class,
    App\Services\CarService::class
);

What is the correct way to do this?

8
  • Where do you write your test? In unit test or in feature test section? Commented Dec 12, 2021 at 7:04
  • @BABAKASHRAFI In unit tests Commented Dec 12, 2021 at 7:04
  • You need to write your test in feature test section, as it's inherited from a custom test case that has CreatesApplication trait in it. Commented Dec 12, 2021 at 7:06
  • @BABAKASHRAFI Well i moved the test to feature section, but i still receive the error. Commented Dec 12, 2021 at 7:10
  • Maybe you have an error in binding. Commented Dec 12, 2021 at 7:18

3 Answers 3

1

You need to write your test in feature section as feature tests are inherited from laravel base test case and they have CreatesApplication trait. Refer to here

After that, you can simply get your concrete class instance using app('Your abstract class namespace ') method or $this->app->make('Your abstract class namespace ') in your test.

1

Obviously the wrong test approach. Why do you need DI in a test class?! In a test class you have to prepare and maybe bind/mock the required classes. And then test your code.

Second part the error says the class are not bind correcly in spite of your assumption.

BTW, if you think I've missed sth, and you need DI, use bind or singleton method.

$this->app->bind(CarServiceInterface::class, fn () => $exampleInstance);

//or 

$this->app->singleton(CarServiceInterface::class, fn () => $exampleInstance);

Now you can use container to access your interface like this without DI error:

$this->app[CarServiceInterface::class]
//or
$this->app->make(CarServiceInterface::class)
//or
app(CarServiceInterface::class)
0

Well i finally found the problem. Although all the given answers/suggesstion by others was also right.
My test case class was extending the wrong TestCase namespace. By changing it to App\TestCase it's got fixed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.