Насмешка над моделью Laravel не работает - все равно идет за базой данных
В настоящее время я пытаюсь следовать шаблону репозитория и попал в ту часть, где мне нужно протестировать репозитории. То, что я пытаюсь проверить, - это вызвать функцию create и высмеивать результат, не затрагивая базу данных. Но при запуске теста я получаю сообщение об ошибке:
PDOException: SQLSTATE[HY000] [2003] Can't connect to MySQL server on 'mysql' (113)
Вот как выглядит мой тестовый файл:
<?php
class UserRepositoryTest extends TestCase
{
private $user;
public function __construct()
{
$this->mock = Mockery::mock('App\User');
$this->user = new \App\Repositories\UserRepository(new Illuminate\Container\Container, new \Illuminate\Support\Collection);
}
public function setUp()
{
parent::setUp();
}
public function tearDown()
{
Mockery::close();
}
public function testCreate()
{
$this->mock
->shouldReceive('create')
->withAnyArgs()
->once()
->andReturn(array());
$user = $this->user->create(['password' => 'secret']);
}
}
Вот как выглядит хранилище пользователя:
<?php
namespace App\Repositories;
use App\Repositories\Eloquent\Repository;
use Illuminate\Support\Facades\Hash;
class UserRepository extends Repository
{
/**
* Specify Model class name.
*
* @return mixed
*/
public function model()
{
return 'App\User';
}
/**
* @param array $data
*
* @return mixed
*/
public function create(array $data)
{
$data['partner_status'] = 'Active';
$data['password'] = Hash::make($data['password']);
return parent::create($data);
}
}
И родительская функция создания выглядит так:
/**
* @param array $data
*
* @return mixed
*/
public function create(array $data)
{
return $this->model->create($data);
}
Как мне посмеяться над тем, чтобы он действительно возвращал то, что я говорю, чтобы он вернулся?
2 ответа
Насмешка над объектом создает один конкретный оскверненный экземпляр. Это не влияет на любой другой код, который создает новые экземпляры этого типа объекта. Например:
$mock = Mockery::mock('App\User');
$user = new \App\User();
В приведенном выше примере $mock
будет экземпляром вашего издевательского объекта, но $user
все равно будет нормальным User
объект, не связанный с макетом вообще.
Этот тест на самом деле ведет вас к лучшему дизайну. В настоящее время ваш UserRepository
имеет скрытую зависимость от \App\User
учебный класс. Чтобы решить эту проблему, вы должны добавить зависимость в конструктор вашего хранилища, чтобы ее можно было внедрить при создании хранилища.
Добавив зависимость в конструктор, она больше не будет скрыта, и вы сможете внедрить свой смоделированный объект вместо попытки создания новых объектов в хранилище, которые, как вы выяснили, труднее тестировать.
Итак, ваш репозиторий будет выглядеть примерно так:
class UserRepository extends Repository
{
public function __construct(\App\User $model, \Illuminate\Container\Container $container, \Illuminate\Support\Collection $collection) {
$this->model = $model;
$this->container = $container;
$this->collection = $collection;
}
}
И тогда ваш тест будет выглядеть примерно так:
class UserRepositoryTest extends TestCase
{
public function __construct()
{
$this->mock = Mockery::mock('App\User');
}
public function testCreate()
{
$this->mock
->shouldReceive('create')
->withAnyArgs()
->once()
->andReturn(array());
$repo = new \App\Repositories\UserRepository($this->mock, new Illuminate\Container\Container, new \Illuminate\Support\Collection);
$user = $repo->create(['password' => 'secret']);
}
}
Вы установили правильную среду тестирования в своем config/database.php
?
Возьмите что-то вроде этого, например:
'testing' => [
'driver' => 'mysql',
'host' => env('DB_TEST_HOST', 'localhost'),
'port' => env('DB_TEST_PORT', '3306'),
'database' => env('DB_TEST_DATABASE', 'homestead_test'),
'username' => env('DB_TEST_USERNAME', 'homestead'),
'password' => env('DB_TEST_PASSWORD', 'secret'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
Затем добавьте новую базу данных с именем homestead_test
, добавьте пользователя с именем homestead
и установите пропуск в secret
,
РЕДАКТИРОВАТЬ: Неважно, я неправильно понял ваш вопрос. Это не поможет вам вообще.