如何测试处理口才模型的Laravel软件包?

时间:2018-09-13 02:55:57

标签: php laravel unit-testing eloquent mocking

我已经创建了一个能够处理雄辩模型的程序包,并且已经为其创建了测试用例。

在某些时候,程序包应该为模型调用save()delete(),这将尝试访问数据库。

实际数据库方法

第一次尝试I tried this approachalso this。关键是,在包的上下文中(甚至使用orchestra/testbench),我需要配置数据库和迁移。由于该程序包本身没有任何模型(但是出于测试目的,我已经创建了 dummy模型),我认为这种方法可能会过大。无论如何,我仍然愿意在内存中设置一个准备好的sqlite db,我也尝试过但不能使其正常工作(它试图使用forge连接代替sqlite,但是我不能让它访问另一个连接。我可能会提供有关它所做的详细信息。

模拟方法

另一种可能的尝试(根据我对此的有限理解)是部分模拟模型。但是在嘲笑它之后,它不知道如何处理其他调用,例如fill(),我愿意这样做,但是我收到了一个未发现异常的方法。

方法替代方法

鉴于这两种可能的尝试都失败了,我默认使用第三种可能对我有用的方法,但老实说,我不确定这是否是解决问题的方法。

为了避免在调用save()delete()方法时由于数据库不足而导致测试失败,我重写了它们(full source code here):

class DummyContact extends Model
{
    // ...

    public function save(array $options = [])
    {
        $this->exists = true;
        $this->wasRecentlyCreated = true;
    }

    public function delete()
    {
        $this->exists = false;
        $this->wasRecentlyCreated = false;
    }
}

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

public function unifyOnBase()
{
    $mergeModel = $this->merge();

    $this->modelA->fill($mergeModel->toArray());
    $this->modelA->save();
    $this->modelB->delete();

    return $this->modelA;
}

所以我的问题是,这种方法可以接受吗? (我认为这很公平,我看不到异常的陷阱,但是我怀疑还有更优雅的方法)。如果有建议的方法,例如模拟或使用实际的数据库运行测试,我想知道what adaptations should I do to my testing codebase进行测试。

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

2 个答案:

答案 0 :(得分:2)

感谢Jonas Staudenmeir的评论:

  

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

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

  1. Removed override functions

  2. Added Capsule test case setUp code按照this working project as example表示感谢(谢谢

  3. 就我而言,我还需要安装sqlite驱动程序sudo apt-get install php7.2-sqlite

Tests now still run successfully,而该解决方案看起来更优雅,并且清理了功能替代解决方法,这些解决方法很容易在Eloquent Models的API升级时中断。这样还可以更轻松地访问测试包中与关系相关的功能。

Test pass

答案 1 :(得分:1)

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

由于您的软件包中没有Eloquent模型,但是您的软件包会修改Eloquent模型,因此我认为您应该仅在测试文件夹中创建Eloquent模型以用于测试。

例如,将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'   => '',
        ]);
    }
}

您可能还想阅读本blog post