模拟 Laravel 模型不工作 - 无论如何都去数据库

Mocking a Laravel model not working - Goes for the database anyway

我目前正在尝试遵循存储库模式,我已经到了需要测试存储库的部分。我要测试的是调用 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);
}

我如何模拟它,使其实际上 return 我告诉它什么 return?

您是否在 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

编辑:没关系,我误读了你的问题。这对你一点帮助都没有。

模拟一个对象会创建一个特定的模拟实例。它不会影响创建该类型对象的新实例的任何其他代码。例如:

$mock = Mockery::mock('App\User');
$user = new \App\User();

在上面的例子中,$mock 将是模拟对象的一个​​实例,但 $user 仍然是一个普通的 User 对象,与模拟对象完全无关。

这个测试实际上是在引导您走向更好的设计之路。目前,您的 UserRepository\App\User class 有隐藏的依赖。要解决此问题,您应该将依赖项添加到存储库的构造函数中,以便在创建存储库时将其注入。

通过将依赖项添加到构造函数,它不再隐藏,您将能够注入您的模拟对象,而不是让存储库尝试创建新对象,这些对象更难测试,因为您发现了。

因此,您的存储库将类似于:

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']);
    }
}