28

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.

7
  • Could you post the constructor for App\Classes\Billing\ShoppingCart please? Commented Nov 17, 2016 at 16:39
  • @edcs Sure thing. Here is the class. pastebin.com/bPRpmtnH Commented Nov 17, 2016 at 16:44
  • 3
    Cool - thanks! You could try using $this->app->make('App\Classes\Billing\ShoppingCart'); as all Laravel tests have an instance of the application available to them as a property. Commented Nov 17, 2016 at 16:54
  • @edcs Thanks for the response. I tried with $this->app->make('App\Classes\Billing\ShoppingCart') and am now getting a new error. Fatal error: Call to a member function make() on null Commented Nov 17, 2016 at 17:07
  • 3
    Just looking at one of my own projects, I never use __construct() to create instances of things. Try renaming __construct() to setupShoppingCart() (or similar - the name doesn't matter) and create a docblock which has @before in it, like this: /** * @before */ Commented Nov 17, 2016 at 17:12

2 Answers 2

62

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.

Sign up to request clarification or add additional context in comments.

1 Comment

You should use setUpBeforeClass() if you want to execute the code only once like __construct() usually does
1

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.

1 Comment

I initially had __construct(...$args) { parent::__construct(...$args); ... } and it failed for tests with data providers. This worked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.