Reputation: 1775
It's my first time with Mockery for PHPUnit. I followed examples from this forum and still getting this error:
Mockery\Exception\InvalidCountException: Method all() from Mockery_0_App_Card should be called exactly 1 times but called 0 times.
Basically, I'm injecting my model in my controller. Like this:
class CardController extends Controller
{
protected $repository;
function __construct(Model $repository)
{
$this->repository = $repository;
}
public function index()
{
$data = $this->repository->all();
return $data;
}
}
And trying testing like this:
class CardTest extends TestCase
{
protected $mock;
protected function setUp(): void
{
parent::setUp();
$this->mock = Mockery::mock('Model', '\App\Card');
}
public function testCardsList()
{
$this->mock->shouldReceive('all')
->once()
->andReturn(json_encode([[
"id"=> 1,
"name"=> "Aut modi quasi corrupti.",
"content"=> "..."
],
[
"id"=> 2,
"name"=> "Voluptas quia distinctio.",
"content"=> "..."
]]));
$this->app->instance('\App\Card', $this->mock);
$response = $this->json('GET', $this->api.'/cards');
$this->assertEquals(200, $response->status(), 'Response code must be 200');
}
}
I've tried a couple of variants but it's always the same. Like, setting Mockery in the controller or using Card::class notation. Any clue?
Also, I'm sure that the response is pulling data from DB and not using the array I provided. So, Mockery is having no incidence on my model.
Upvotes: 1
Views: 1569
Reputation: 1775
After some readings, I'm convinced that testing with a SQLite DB is way better than creating mockups for Models. You don't have to work that much creating mockups. I'm linking to some discussion threads about how to implement the test environment, but I'm also pasting the code the I ended up writing.
Basically, you have to configure the DB to be SQLite. And you'll declare that it will run in memory. That's much faster than using a file.
Then, you want to run your migrations. And in my case, also seed the DB.
<?php
namespace Tests;
use DirectoryIterator;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
protected function setUp()
{
parent::setUp();
Config::set('database.connections.sqlite.database', ':memory:');
Config::set('database.default', 'sqlite');
Artisan::call('migrate');
Artisan::call('db:seed');
protected function tearDown()
{
Artisan::call('migrate:reset');
parent::tearDown();
}
}
There's a caveat: setUp()
is called once for each test. And I find out that this kind of notation will not work because the DB will be regenerated each time:
@depends testCreateCard
I was using that notation to pass an ID from testCreate()
to several other methods. But ended up trusting in my seeds and using a hardcoded value.
Refs:
Upvotes: 1