Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Unit Testing Dependency Injection

I'm trying to write a test class for a shopping cart. Here is what I have:

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);
    }

}

However, when I run phpunit, it seems like Laravel is unable to resolve my ShoppingCartClass.

Here is the error:

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

I have my ShoppingCart class being resolved in a number of different controllers just fine.

Why can't Laravel resolve it during my tests?

I refered to this post as well but still didn't have any luck.

like image 656
Denis Priebe Avatar asked Nov 17 '16 14:11

Denis Priebe


2 Answers

I figured it out. Here is the updated class.

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);
    }

}

Thanks to @edcs for guiding me in the right direction. You need to use a setUp function and not __construct as the app instance hasn't been created yet.

like image 144
Denis Priebe Avatar answered Nov 17 '22 18:11

Denis Priebe


If you want to use __construct you have to use the same constructor of PHPUnit\Framework\TestCase and remember to call the parent method if you don't want to break anything

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

        // my init code
    }
}

However the proper way would be to use the method setUpBeforeClass() if you want to execute your init code once or setUp() if you want to execute the init code before each test contained in your class. Check PHPUnit documentation for more details.

like image 1
Andrea Mauro Avatar answered Nov 17 '22 18:11

Andrea Mauro