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:

  1. Laravel 5 - Использование насмешек для насмешки над моделью Eloquent
  2. https://www.patrickstephan.me/post/setting-up-a-laravel-5-test-database.html
  3. https://laracasts.com/discuss/channels/testing/how-to-specify-a-testing-database-in-laravel-5
  4. https://laracasts.com/discuss/channels/general-discussion/how-to-migrate-a-testing-database-in-laravel-5
Другие вопросы по тегам