Question

I am trying to test my controller with this test (I'm using Laravel, if that matters):

<?php
use Zizaco\FactoryMuff\Facade\FactoryMuff;

class ProjectControllerTest extends TestCase
{
    public function setUp()
    {
        parent::setUp();

        $this->mock = $this->mock('Dumminvoicing\Storage\Project\ProjectRepositoryInterface');
    }

    public function mock($class)
    {
        $mock = Mockery::mock($class);

        $this->app->instance($class, $mock);

        return $mock;
    }

    protected function tearDown()
    {
        Mockery::close();
    }

    public function testRedirectWhenNotLogged()
    {
        Route::enableFilters();
        $response = $this->call('GET', 'projects');
        $this->assertRedirectedToAction('UserController@getLogin');
    }

    public function testAllowedWhenLogged()
    {
        Route::enableFilters();
        //Create user and log in
        $user = FactoryMuff::create('User');
        $this->be($user);
        $response = $this->call('GET', 'projects');
        $this->assertResponseOk();
    }

    public function testIndex()
    {
        $this->mock->shouldReceive('all')->once();
        $this->call('GET', 'projects');
        $this->assertViewHas('projects');
    }

}

Following these tutorials http://culttt.com/2013/07/08/creating-flexible-controllers-in-laravel-4-using-repositories/ http://culttt.com/2013/07/15/how-to-structure-testable-controllers-in-laravel-4/ I use repositories to avoid coupling my DB to the tests. So I have these 2 extra classes:

<?php
namespace Dumminvoicing\Storage\Project;

use Project;
class EloquentProjectRepository implements ProjectRepository
{
    public function all()
    {
        return Project::all();
    }

    public function find($id)
    {
        return Project::find($id);
    }
}

<?php
namespace Dumminvoicing\Storage\Project;

interface ProjectRepository
{
    public function all();
    public function find($id);
}

When I run the test, I get this error:

There was 1 error:

1) ProjectControllerTest::testIndex Mockery\Exception\InvalidCountException: Method all() from Mockery_2143809533_Dumminvoicing_Storage_Project_ProjectRepositoryInterface should be called exactly 1 times but called 0 times.

The index method of the controller works fine in the browser:

     use Dumminvoicing\Storage\Project\ProjectRepository as Project;

    class ProjectsController extends \BaseController
    {
        protected $project;

        public function __construct(Project $project)
        {
            $this->project = $project;

            $this->beforeFilter('auth');
        }
    }
/**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $data['projects'] = $this->project->all();
        return View::make('projects.index', $data) ;
    }

So why is it failing in the test? Why is "all" not being called?

Was it helpful?

Solution

If the user has to be authenticated to hit the index method, you need to authenticate each test.

The all isn't getting called because the user is being redirected.

Create an authentication method that you can call each time you need to authenticate the request.

To see why the test failing, dump out the response before you do the assert.

Edit

The problem is you've mocked Dumminvoicing\Storage\Project\ProjectRepositoryInterface but it should be Dumminvoicing\Storage\Project\ProjectRepository.

If you correct the namespace and add $this->mock->shouldReceive('all')->once(); to the testAllowedWhenLogged() method your tests will pass correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top