Инъекция зависимостей от Laravel Unit Testing Injection

Я пытаюсь написать тестовый класс для корзины покупок. Вот что я имею:

ShoppingCartTest.php

class ShoppingCartTest extends TestCase {

    use DatabaseTransactions;

    protected $shoppingCart;

    public function __construct() {
        $this->shoppingCart = resolve('App\Classes\Billing\ShoppingCart');
    }

    /** @test */
    public function a_product_can_be_added_to_and_retrieved_from_the_shopping_cart() {

        // just a placeholder at the moment
        $this->assertTrue(true);
    }

}

Однако, когда я запускаю phpunit, похоже, что Laravel не может разрешить мой ShoppingCartClass.

Вот ошибка:

Fatal error: Uncaught exception 'Illuminate\Contracts\Container\BindingResolutionException'
with message 'Unresolvable dependency resolving
[Parameter #0 [ <required> $app ]] in class Illuminate\Support\Manager'
in C:\Development Server\EasyPHP-Devserver-16.1\eds-www\nrponline\vendor\laravel\framework\src\Illuminate\Container\Container.php:850

У меня есть класс ShoppingCart, который разрешается в целом ряде различных контроллеров.

Почему Laravel не разрешает это во время моих тестов?

Я ссылался на этот пост, но все равно не повезло.

Ответ 1

Я понял это. Вот обновленный класс.

class ShoppingCartTest extends TestCase {

    use DatabaseTransactions;

    protected $shoppingCart;

    public function setUp() {

        parent::setUp();

        $this->shoppingCart = $this->app->make('App\Classes\Billing\ShoppingCart');
    }

    /** @test */
    public function a_product_can_be_added_to_and_retrieved_from_the_shopping_cart() {

        // just a placeholder at the moment
        $this->assertTrue(true);
    }

}

Благодаря @edcs для руководства меня в правильном направлении. Вам нужно использовать функцию setUp, а не __construct, поскольку экземпляр app еще не создан.

Ответ 2

Если вы хотите использовать __construct вы должны использовать тот же конструктор PHPUnit\Framework\TestCase и не забывать вызывать родительский метод, если вы не хотите ничего ломать

class MyTest extends TestCase
{
    public function __construct($name = null, array $data = [], $dataName = '')
    {
        parent::__construct($name, $data, $dataName);

        // my init code
    }
}

Однако правильным способом было бы использовать метод setUpBeforeClass() если вы хотите выполнить код инициализации один раз, или setUp() если вы хотите выполнить код инициализации перед каждым тестом, содержащимся в вашем классе. Проверьте документацию PHPUnit для более подробной информации.