代码之家  ›  专栏  ›  技术社区  ›  Ryukish

嘲笑拉拉维夫模型不起作用-无论如何都要用数据库

  •  3
  • Ryukish  · 技术社区  · 8 年前

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

    父级的create函数如下所示:

    /**
     * @param array $data
     *
     * @return mixed
     */
    public function create(array $data)
    {
        return $this->model->create($data);
    }
    

    我如何嘲笑它,使它真正返回我告诉它返回的内容?

    2 回复  |  直到 8 年前
        1
  •  4
  •   patricus    8 年前

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

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

    在上面的例子中, $mock 将是模拟对象的实例,但 $user 还是正常的 User 对象,与mock完全无关。

    这个测试实际上是在引导您走向更好的设计。目前,您的 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']);
        }
    }
    
        2
  •  0
  •   Loek    8 年前

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

    编辑:没关系,我误读了你的问题。这对你毫无帮助。