Laravel 5.4 Модель макета для PHPunit
Я впервые использую Mockery для PHPUnit. Я следовал за примерами с этого форума и все еще получаю эту ошибку:
Mockery \ Exception \ InvalidCountException: метод all() из Mockery_0_App_Card должен вызываться ровно 1 раз, но вызываться 0 раз.
По сути, я внедряю свою модель в мой контроллер. Как это:
class CardController extends Controller
{
protected $repository;
function __construct(Model $repository)
{
$this->repository = $repository;
}
public function index()
{
$data = $this->repository->all();
return $data;
}
}
И пробуем тестирование так:
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');
}
}
Я пробовал пару вариантов, но это всегда то же самое. Например, установка Mockery в контроллере или использование нотации Card::class. Любая подсказка?
Кроме того, я уверен, что ответ извлекает данные из БД и не использует предоставленный мною массив. Итак, насмешка не имеет отношения к моей модели.
1 ответ
После некоторых чтений я убежден, что тестирование с базой данных SQLite намного лучше, чем создание макетов для моделей. Вам не нужно много работать над созданием макетов. Я ссылаюсь на некоторые темы обсуждения о том, как реализовать тестовую среду, но я также вставляю код, который я в итоге написал.
По сути, вы должны настроить БД на SQLite. И вы объявите, что он будет работать в памяти. Это намного быстрее, чем с помощью файла.
Затем вы хотите запустить свои миграции. И в моем случае также начальная база данных.
<?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();
}
}
Есть предостережение: setUp()
вызывается один раз для каждого теста. И я обнаружил, что этот вид записи не будет работать, потому что БД будет обновляться каждый раз: @depends testCreateCard
Я использовал эту запись, чтобы передать идентификатор от testCreate()
к нескольким другим методам. Но в конечном итоге я поверил в мои семена и использовал жестко закодированное значение.
Refs:
- Laravel 5 - Использование насмешек для насмешки над моделью Eloquent
- https://www.patrickstephan.me/post/setting-up-a-laravel-5-test-database.html
- https://laracasts.com/discuss/channels/testing/how-to-specify-a-testing-database-in-laravel-5
- https://laracasts.com/discuss/channels/general-discussion/how-to-migrate-a-testing-database-in-laravel-5