嘲弄Laravel模型不起作用 - 无论如何都去了数据库

时间:2016-06-16 13:02:37

标签: php unit-testing laravel mocking mockery

我目前正在尝试遵循存储库模式,而且我已经到了需要测试存储库的部分。我试图测试的是调用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 个答案:

答案 0 :(得分: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']);
    }
}

答案 1 :(得分:0)

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

编辑:没关系,我误解了你的问题。这对你没有任何帮助。