【问题标题】:Problem with testing database laravel 7.x测试数据库 laravel 7.x 的问题
【发布时间】:2021-07-18 12:24:07
【问题描述】:

我正在尝试在 laravel 7.x 中进行单元测试。

我创建了一个测试数据库,该数据库与我用于我的网站的数据库相同。

我修改了 phpunit.xml 文件,我创建了一个 .env.testing 文件并添加了一个到 database.php 文件,但我得到一个 "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'cbs_perform_test.cbs_defis' doesn't exist (SQL: select count(*) as aggregate from cbs_defis )" 错误。

我已经多次检查了数据库和表的名称,以确保我使用的是正确的。

我已经遵循了这些指南:Use different database for testing and localHow to Specify a Separate Database for Unit Testing on Laravel 5

这是我的 phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="testing"/>
        <server name="DB_DATABASE" value="cbs_perform_test"/>
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <env name="DB_CONNECTION" value="testing"/>
    </php>

我的 database.php 连接

'testing' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => false,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

我的 .env.testing 文件

APP_ENV=testing

DB_CONNECTION=testing
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cbs_perform_test
DB_USERNAME=root
DB_PASSWORD=

我的测试代码

class DefiTest extends TestCase
{
    use DatabaseMigrations;
    use DatabaseTransactions;

    /**
     * A basic unit test example.
     *
     * @return void
     */
    public function testCreateDefi()
    {
        $request = new Request();
        $request->DEF_NOM = 'test';
        $request->DEF_DESCRIPTION = 'testdescriptio ajhsg ln';
        $request->DEF_NBSEMAINES = 2;
        $request->DEF_CONSEILS = 'jhasnciu launh sl';
        $request->DEF_VISIBLE = 1;
        $request->DEF_DATE_VISIBLE = Carbon::now()->toDate();
        $request->COA_ID = 3;

        $dfc = new DefiCoachController();
        $response = $dfc->createDefiTest($request);

        $this->assertDatabaseHas('cbs_defis', $request->all());
    }
}

我用于测试的命令:php artisan test --env=testing

【问题讨论】:

    标签: php mysql laravel


    【解决方案1】:

    首先,希望我能帮助您解决问题,因为我很确定这是您在连接的某个地方犯的一个愚蠢的错误。

    所以,这里有一些提示:

    不要测试你的代码“调用”核心框架代码...

    而不是做(单元测试):

    $request = new Request();
    $request->DEF_NOM = 'test';
    $request->DEF_DESCRIPTION = 'testdescriptio ajhsg ln';
    $request->DEF_NBSEMAINES = 2;
    $request->DEF_CONSEILS = 'jhasnciu launh sl';
    $request->DEF_VISIBLE = 1;
    $request->DEF_DATE_VISIBLE = Carbon::now()->toDate();
    $request->COA_ID = 3;
    
    $dfc = new DefiCoachController();
    $response = $dfc->createDefiTest($request);
    
    $this->assertDatabaseHas('cbs_defis', $request->all());
    

    做(功能测试):

    $data = [
        'nom' => 'test',
        'description' => 'testdescriptio ajhsg ln',
        'nbsemaines' => 2,
        'conseils' => 'jhasnciu launh sl',
        'visible' => 1,
        'date_visible' => Carbon::now()->toDate(),
        'coa_id' => 3,
    ];
    
    $response = $this->post('your_desired_url_for_this_action', $data); // This can be get, post, put or delete
    
    $this->assertDatabaseHas('cbs_defis', $data);
    

    这样,您可以确保:

    1. 您的网址是您想要的,没有任何拼写错误或任何错误
    2. 控制器正在做它应该做的事情,在这种情况下插入数据。
    3. 控制器正在插入您希望它插入的数据。假设你在窗帘后面有一些处理,在这里你可以确保你发送了“1和3”并插入了“角色X”(这是一个例子,假设这将是你在处理1和3之后想要的结果,所以你不是直接插入1 and 3)
    4. 始终避免从您正在测试的地方断言数据。在您的情况下,您正在使用Request 对象,假设它是您的自定义类,并且您在执行$request-&gt;attribute1 = 2 时会执行某些操作,因此当您将其读回为$request-&gt;attribute1 时,您可能已经完成了一些过程来存储它并且你已经修改了它......如果你断言没有明确说assert that attribute1 is what I expect 你永远不会断言它。如果您的代码有错误,而不是返回 b1 = a2 = b 等),代码将始终通过,因为您将其存储为其他内容预期的,但你断言它已经做了什么(假设你的错误返回c而不是b)所以你说“在数据库中查找$request-&gt;attribute1”并且你将存储c而不是b(你的期望值),它仍然会找到它并通过测试。

    如果除了DB_DATABASE 或类似之外,它都相同,则无需创建新的connection。在这种情况下,您只需在 .env.testingphpunit.xml 中定义该信息。

    另外,不需要&lt;server name="DB_CONNECTION" value="testing"/&gt;&lt;env name="DB_CONNECTION" value="testing"/&gt;。如果你看到 Laravel GitHub 的 phpunit.xml,你会看到他们在 5.7+ 上将 &lt;env&gt; 更改为 &lt;server&gt;,所以坚持使用与你的版本对应的那个。有区别,虽然现在记不起来了,但是测试起来没问题。


    所以,请确保您设置了正确的DB_HOSTDB_PORTDB_USERNAMEDB_PASSWORD。您可以拥有相同的主机但不同的端口,或者您可以拥有相同的主机和端口但不同的数据库名称,但相同的用户名和密码。所以请确保您连接到正确的数据库。

    由于您的错误是找不到所需的表,显然您正在连接到数据库,因此用户名和密码不应该是您的问题,但该表不存在。


    最后一件重要的事情,您是否在测试中使用了任何特征?有一些特征可以自动迁移数据库并在完成后将其回滚,因此您无需在测试环境中手动同步迁移。你应该使用use RefreshDatabase; trait 来这样做。


    最后一个提示,尽量避免使用DEF_SOMETHING,因为:

    1. 如果你的控制器和Defi相关,就不用说“这是DEF数据”了,我们已经知道了,直接做something即可。数据库也一样,如果表名是cars,避免car_wheelscar_doors等,做wheelsdoors等。
    2. 避免使用X_Y,更喜欢使用x_y,对于数据库也是如此。始终坚持小写,对于数据库,坚持snake_case,但对于模型的属性,始终坚持camelCase。 (more info关于案例)

    【讨论】:

    • 非常感谢您的回答。对我帮助很大
    • 很高兴对您有所帮助!我喜欢这样做并帮助测试!
    猜你喜欢
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 2014-12-31
    • 2014-09-03
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多