Как протестировать пакет Laravel, который обрабатывает модели Eloquent?

Я создал пакет, который управляет красноречивыми моделями, и создал для него тестовые примеры.

Пакет должен в какой-то момент вызвать save() или delete() для моделей, которые попытаются попасть в базу данных.

Актуальный подход к базе данных

В качестве первой попытки Я пробовал этот подход и также это. Дело в том, что в контексте пакета (даже с использованием orchestra/testbench) мне нужно будет настроить базу данных и миграции. Поскольку в самом пакете нет модели (но я создал манекен для целей тестирования), я считаю этот подход излишним. В любом случае, я бы все равно согласился установить подготовленный sqlite db в памяти, который я также пробовал, но не смог заставить его работать (он пытался использовать соединение forge вместо sqlite, и я не мог заставить его получить доступ к другому соединению. Я могу расскажите подробнее о том, что я для этого сделал).

Издевательский подход

Другая возможная попытка (в соответствии с моим ограниченным пониманием этого) - частично имитировать модель. Но после того, как я поиздевался над ним, он не знал, как обрабатывать другие вызовы, такие как fill(), для которых я желал общего поведения, но я получил исключение метода не найден.

Подход с переопределением метода

Учитывая, что эти две возможные попытки не увенчались успехом, я по умолчанию выбрал третий возможный подход, который сработал для меня, но я, честно говоря, не уверен, что это способ сделать это.

Чтобы избежать сбоя теста из-за отсутствия базы данных при вызове методов save() или delete(), я переопределил их (полный исходный код здесь):

class DummyContact extends Model
{
    // ...

    public function save(array $options = [])
    {
        $this->exists = true;
        $this->wasRecentlyCreated = true;
    }

    public function delete()
    {
        $this->exists = false;
        $this->wasRecentlyCreated = false;
    }
}

Таким образом, я могу протестировать следующий код (полный источник здесь):

public function unifyOnBase()
{
    $mergeModel = $this->merge();

    $this->modelA->fill($mergeModel->toArray());
    $this->modelA->save();
    $this->modelB->delete();

    return $this->modelA;
}

Итак, мой вопрос: приемлем ли такой подход? (Думаю, это справедливо, я не вижу исключительных ловушек, но подозреваю, что существуют более элегантные подходы). В случае, если есть предлагаемые подходы, такие как Mocking или использование реальной БД для запуска тестов, я хотел бы знать какие адаптации я должен сделать с моей тестовой кодовой базой для их выполнения.

Последнее, но важное замечание: Я не хочу тестировать сами модели, я хочу протестировать свой код, который использует (и, следовательно, зависит от моделей).

Интеграционный тест с реальной базой данных - самый тщательный способ проверить ваш код. ИМО, у вас должны быть хотя бы интеграционные тесты для основных функций. Этот - это то, как я использую базу данных SQLite для тестов моего пакета.

Jonas Staudenmeir 15.09.2018 00:07

Это вроде того, что id хочет получить. Попробую объединить ваш подход и опубликовать результаты. Спасибо за реф.

alariva 15.09.2018 00:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
5
2
963
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Спасибо за комментарий Йонаса Штауденмейра:

An integration test with an actual database is the most thorough way to test your code. IMO, you should at least have integration tests for the fundamental features. This is how I use an SQLite database for the tests of my package.

Я мог бы объединиться и приступить к работе по подходу sqlite в памяти.

  1. Удалены функции переопределения

  2. Добавлен набор тестовых примеров Capsule. согласно этот рабочий проект как пример (Спасибо за это)

  3. В моем случае мне также потребовалось установить драйвер sqlite sudo apt-get install php7.2-sqlite

Теперь тесты по-прежнему проходят успешно, в то время как решение выглядит более элегантным и очищает обходные пути переопределения функций, которые легко сломались бы при обновлении API Eloquent Models. Это также упростит доступ к тестированию зависимых от отношений функций пакета.

Test pass

Я думаю, что ваше первое предложение, актуальный подход к базе данных, является лучшим - с использованием пакета оркестр / испытательный стенд.

Поскольку у вас нет моделей Eloquent в вашем пакете, но ваш пакет изменяет модели Eloquent, я думаю, вам следует создавать модель Eloquent только для целей тестирования внутри своей тестовой папки.

Например, поместите DummyContact в tests/Models/DummyContact.php и поместите файл миграции в tests/Database/Migration/DummyContactMigration.php.

Теперь все, что вам нужно сделать, это установить базовый TestCase.php. Убедитесь, что вы явно вызываете файл миграции вашей модели DummyContact.

Вот пример:

<?php

namespace MyVendor\MyPackage\Tests;

use MyVendor\MyPackage\MyServiceProvider;

class TestCase extends \Orchestra\Testbench\TestCase
{
    public function setUp(): void
    {
        parent::setUp();

        $this->loadMigrationsFrom(__DIR__ . '/database/migrations');
        $this->artisan('migrate', ['--database' => 'testbench'])->run();

    }

    /**
     * add the package provider
     *
     * @param $app
     * @return array
     */
    protected function getPackageProviders($app)
    {
        return [MyServiceProvider::class];
    }

    /**
     * Define environment setup.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    protected function getEnvironmentSetUp($app)
    {
        // Setup default database to use sqlite :memory:
        $app['config']->set('database.default', 'testbench');
        $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => '',
        ]);
    }
}

Вы также можете прочитать этот Сообщение блога

Другие вопросы по теме