I am about $this->close() to giving up on Mockery in my unit tests. Here's what's going on, I am working with Laravel 5.1 and I'm trying to test my repository pattern abstraction using Mockery in PHPUnit. I've followed the tutorials, poured over the StackOverflow questions so it's not a duplicate. When you see anything about modules here, it's PingPong Sky Modules package.
Basically, when I try to mock the repository interface and set shouldReceive('create')->with([])->once()
, Mockery throws:
Mockery\Exception\InvalidCountException: Method create(array()) from Mockery_0_Modules_Documents_Repositories_DocumentRepositoryInterface should be called exactly 1 times but called 0 times.
DocumentsTest.php
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
class FileUploadTest extends TestCase {
use WithoutMiddleware;
public function mock($class){
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
public function testFileUpload(){
// Mock the Repository
$mock = $this->mock('\Modules\Documents\Repositories\DocumentRepositoryInterface');
$mock->shouldReceive('create')->with([])->once();
$this->call('POST', '/documents', [], [], []);
$this->assertResponseStatus(201);
}
}
DocumentRepositoryInterface.php
<?php namespace Modules\Documents\Repositories;
interface DocumentRepositoryInterface {
public function create(array $data);
}
DatabaseDocumentRepository.php
<?php namespace Modules\Documents\Repositories;
use Modules\Documents\Repositories\DocumentRepositoryInterface;
use \Illuminate\Database\Eloquent\Model;
class DatabaseDocumentRepository implements DocumentRepositoryInterface {
protected $documents;
public function __construct(Model $documents) {
$this->documents = $documents;
}
public function create(array $data) {
// Eloquent code.
return "response";
}
}
Document.php
<?php namespace Modules\Documents\Entities;
use Illuminate\Database\Eloquent\Model;
class Document extends Model {
protected $fillable = [];
}
routes.php
$this->app->bind(
'Modules\Documents\Repositories\DocumentRepositoryInterface', function(){
return new Modules\Documents\Repositories\DatabaseDocumentRepository(new Modules\Documents\Entities\Document());
});
Route::group(['prefix' => 'documents', 'namespace' => 'Modules\Documents\Http\Controllers'], function(){
Route::post('/', ['as' => '/', 'uses'=> 'DocumentsController@create']);
});
DocumentsController.php
<?php namespace Modules\Documents\Http\Controllers;
use Modules\Documents\Repositories\DocumentRepositoryInterface;
use Pingpong\Modules\Routing\Controller;
use Module;
use Illuminate\Http\Response;
use Illuminate\Http\Request;
class DocumentsController extends Controller {
private $documents;
public function __construct(DocumentRepositoryInterface $doc){
$this->documents = $doc;
}
public function create(Request $request){
$this->documents->create([]);
return response("", Response::HTTP_CREATED);
}
}
I want to say it has something to do with the mocked object not getting injected into the DocumentsController because the create() function is getting called. I put a print_r in the create function and it displayed in my console. This is strange and it could also be related to PingPong Sky Modules. What am I doing wrong or not doing?