Я создал пакет, который управляет красноречивыми моделями, и создал для него тестовые примеры.
Пакет должен в какой-то момент вызвать 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 или использование реальной БД для запуска тестов, я хотел бы знать какие адаптации я должен сделать с моей тестовой кодовой базой для их выполнения.
Последнее, но важное замечание: Я не хочу тестировать сами модели, я хочу протестировать свой код, который использует (и, следовательно, зависит от моделей).
Это вроде того, что id хочет получить. Попробую объединить ваш подход и опубликовать результаты. Спасибо за реф.






Спасибо за комментарий Йонаса Штауденмейра:
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 в памяти.
Добавлен набор тестовых примеров Capsule. согласно этот рабочий проект как пример (Спасибо за это)
В моем случае мне также потребовалось установить драйвер sqlite sudo apt-get install php7.2-sqlite
Теперь тесты по-прежнему проходят успешно, в то время как решение выглядит более элегантным и очищает обходные пути переопределения функций, которые легко сломались бы при обновлении API Eloquent Models. Это также упростит доступ к тестированию зависимых от отношений функций пакета.
Я думаю, что ваше первое предложение, актуальный подход к базе данных, является лучшим - с использованием пакета оркестр / испытательный стенд.
Поскольку у вас нет моделей 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' => '',
]);
}
}
Вы также можете прочитать этот Сообщение блога
Интеграционный тест с реальной базой данных - самый тщательный способ проверить ваш код. ИМО, у вас должны быть хотя бы интеграционные тесты для основных функций. Этот - это то, как я использую базу данных SQLite для тестов моего пакета.