Php 如何测试处理雄辩模型的Laravel软件包?

Php 如何测试处理雄辩模型的Laravel软件包?,php,laravel,unit-testing,eloquent,mocking,Php,Laravel,Unit Testing,Eloquent,Mocking,我已经创建了一个处理有说服力的模型的包,并且为它创建了测试用例 软件包应该在某个时候为模型调用save()或delete(),这将试图访问数据库 实际数据库方法 作为第一次尝试。关键是,在包的上下文中(甚至使用orchestra/testbench),我需要配置数据库和迁移。因为包本身没有任何模型(但我已经为测试目的创建了一个虚拟模型),所以我认为这种方法可能有些过分。在任何情况下,我仍然愿意在内存中设置一个准备好的sqlite db,我也尝试过,但无法让它工作(它试图使用forge连接来代替s

我已经创建了一个处理有说服力的模型的包,并且为它创建了测试用例

软件包应该在某个时候为模型调用
save()
delete()
,这将试图访问数据库

实际数据库方法 作为第一次尝试。关键是,在包的上下文中(甚至使用
orchestra/testbench
),我需要配置数据库和迁移。因为包本身没有任何模型(但我已经为测试目的创建了一个虚拟模型),所以我认为这种方法可能有些过分。在任何情况下,我仍然愿意在内存中设置一个准备好的sqlite db,我也尝试过,但无法让它工作(它试图使用
forge
连接来代替
sqlite
,我无法让它访问另一个连接。我可以提供关于我为它做了什么的详细信息)

模仿法 另一种可能的尝试(根据我对此的有限理解)是部分模拟模型。但是,在我模拟它之后,它将不知道如何处理其他调用,例如
fill()
,我愿意使用常见的行为,但是我收到了一个method not found exception

方法覆盖方法 考虑到这两种可能的尝试都失败了,我默认了第三种可能的方法,这对我来说是有效的,但我真的不确定这是否是解决问题的方法

为了避免调用
save()
delete()
方法时由于缺少数据库而导致测试失败,我覆盖了它们():

这样,我就可以测试以下代码():

所以我的问题是,这种方法可以接受吗?(我认为这是公平的,我没有看到异常的陷阱,但我怀疑存在更优雅的方法)。如果有建议的方法,比如模拟或使用实际的DB来运行测试,我想知道如何使用它们


最后但重要的注意事项:我不愿意测试模型本身,我愿意测试使用的代码(因此取决于模型)。

感谢Jonas Staudenmeir的评论:


与实际数据库的集成测试是测试代码最彻底的方法。依我看,您至少应该对基本功能进行集成测试。我使用SQLite数据库来测试我的包

我可以配对并开始使用内存sqlite方法

  • 根据(谢谢)

  • 在我的例子中,我还需要安装sqlite驱动程序
    sudo apt get install php7.2-sqlite

  • ,而该解决方案看起来更优雅,并清理了函数覆盖解决方案,该解决方案在对有说服力的模型进行API升级时很容易被打破。这还可以更容易地访问包的测试关系相关特性


    我认为您的第一个建议,实际的数据库方法是最好的-使用包

    因为您的包中没有雄辩的模型,但是您的包修改了雄辩的模型,所以我认为您应该在测试文件夹中创建一个只用于测试目的的雄辩的模型

    例如,将
    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数据库来测试我的软件包的。这是我想开始工作的部分。我会尝试将您的方法与发布结果配对。谢谢参考
    
    public function unifyOnBase()
    {
        $mergeModel = $this->merge();
    
        $this->modelA->fill($mergeModel->toArray());
        $this->modelA->save();
        $this->modelB->delete();
    
        return $this->modelA;
    }
    
    <?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'   => '',
            ]);
        }
    }