1

I am getting stuck at a test where I want to Unit test my UserRepository for my application.

I have a class:

<?php
class EloquentUserRepository implements UserRepository {}
?>

And I want to inject that into my Unit test here:

<?php
use Converse\User\UserRepository as User;

class UserRepositoryTest extends TestCase
{
    protected $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }
}
?>

I am getting this exception:

Catchable fatal error: Argument 1 passed to UserRepositoryTest::__construct() must be an instance of Converse\User\UserRepository, none given, called in C:\Zend\Apache2\htdocs\pear\PHPUnit\Framework\TestSuite.php on line 473 and defined in C:\Zend\Apache2\htdocs\workspace\projects\converse\src\app\t ests\Users\UserRepositoryTest.php on line 17

I can't seem to figure out why this repository is not available for injection for my unit test? Please assist?

Etienne Marais
  • 1,660
  • 1
  • 22
  • 40
  • Could you provide the contents of UserRepositoryTest? My guess is that you haven't mocked up your User class to pass to your controller. There doesn't appear to be much to test in that class though. – kreeves Dec 16 '13 at 15:26
  • @kreeves That is the contents of my Test. I wanted to start out testing my User model, which is abstracted by an EloquentUserRepository class. I need to pass that class into my test but it does not seem to be available – Etienne Marais Dec 16 '13 at 16:36
  • 1
    Ah whoops, I read your code incorrectly. I'll blame that on not yet having my coffee. :] – kreeves Dec 16 '13 at 16:57

2 Answers2

2

You shouldn't be using the constructor for that. Instead, use setUp() and tearDown() methods to create all objects and dependencies that you need in your tests.

use Converse\User\UserRepository as User;

class UserRepositoryTest extends TestCase
{
    protected $user;

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

        // Assuming you've already bound the class somewhere
        $this->user = $this->app->make('Converse\User\UserRepository');
    }
}

I can't really tell the reason for this, but if you take a look at some of your vendor packages in Laravel, all of them are doing it this way.


Also, this question seems to be related although it's about Java:

Community
  • 1
  • 1
Manuel Pedrera
  • 5,347
  • 2
  • 30
  • 47
  • One caveat is I believe you need to call parent::setUp() otherwise the setUp() function won't work. At least, this was the case a couple months ago. – patricksayshi Dec 16 '13 at 18:16
  • Yes, that's right. I forgot we are talking about `TestCase` and not `PHPUnit_Framework_TestCase`. Updated code with parent call. – Manuel Pedrera Dec 16 '13 at 18:21
  • This is the solution. The app make() resolves this nicely thanks. NOTE: This is not the mock object, this is the actual object to test data values in memory sqlite. – Etienne Marais Dec 17 '13 at 08:25
1

EDIT: I'd ignore this in favor of Manuel Padrera's answer.

Are you binding EloquentUserRepository to the UserRepository interface anywhere in the IoC container? You could do that in a service provider or by using App:bind(). It looks to me like you are passing the interface itself as a parameter to the test. Although usually in that case you would get a "not instantiable" error rather than just "none given."

patricksayshi
  • 1,395
  • 3
  • 13
  • 18
  • Yes I am already binding it. The IoC container cannot seem to find it in the test environment though. – Etienne Marais Dec 16 '13 at 16:35
  • 1
    Ahh, that's right. Are you sure you want to use constructor injection for the unit test class itself? You might try using `public function setUp() { parent::setUp(); $this->user = new User(); }` or something to that effect instead. Even better would be to mock the User class instead. Mockery is pretty great for that. – patricksayshi Dec 16 '13 at 16:54
  • Here's how you mock objects using PHPUnit --- http://phpunit.de/manual/3.0/en/mock-objects.html – patricksayshi Dec 16 '13 at 16:56
  • 2
    Some recommend using the getMockBuilder as a simpler way to mock directly in PHPUnit. http://phpunit.de/manual/3.7/en/test-doubles.html#test-doubles.stubs.examples.StubTest2.php has an example. – kreeves Dec 16 '13 at 17:06