测试数据库laravel 7.x的问题 [英] Problem with testing database laravel 7.x

查看:63
本文介绍了测试数据库laravel 7.x的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to do unit testing in laravel 7.x.

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

I created a testing database which is identic to the database I use for my website.

我修改了 phpunit.xml 文件,创建了 .env.testing 文件,并在其中添加了测试"连接到 database.php 文件,但是我得到的是" SQLSTATE [42S02]:找不到基表或视图:1146表'cbs_perform_test.cbs_defis'不存在(SQL:从 cbs_defis )" 错误中选择count(*)作为汇总.

I modified the phpunit.xml file, I created a .env.testing file and I added a "testing" connection to the database.php file but I am getting an "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)" error.

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

I already checked multiple times the name of the database and the table to be sure I am using the correct one.

我已经遵循以下指南:使用其他数据库进行测试和本地如何为Laravel 5上的单元测试指定单独的数据库

I already followed these guides : Use different database for testing and local ; How 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

推荐答案

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

First of all, hope I can help you fix your problem as I am pretty sure it is a silly mistake you are making somewhere in the connection.

因此,这里有一些提示:

So, here are some tips:

请勿对您的代码调用"测试.核心框架代码...

Do not test your code "invoking" core framework code...

代替做(单元测试):

$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. 您的URL是您想要的URL,没有任何错字或任何错误
  2. 控制器正在执行应做的事情,在这种情况下插入数据.
  3. 控制器正在插入要插入的数据.假设您在幕后进行了一些处理,在这里您可以确保发送了"1和3"并在其中插入了角色X"(这是一个示例,假设在处理完1和3之后,这将是您想要的结果,因此您不会直接插入 1和3 ))
  4. 始终避免从测试位置声明数据.在您的情况下,您正在使用 Request 对象,假设它是您的自定义类,并且在执行 $ request-> attribute1 = 2 时会执行某些操作,所以当您以 $ request-> attribute1 的形式读回它,也许您已经完成了一些存储它的过程并对其进行了修改...如果您断言没有明确说出断言attribute1是我所期望的您永远不会断言.如果您的代码有误,而不是返回 b ( 1 = a 2 = b 等),因为您将代码存储为非预期的东西,但代码始终会通过,但是您要断言它已经完成了什么(假设您的错误返回了 c 而不是 b ),因此您说的是在数据库中找到 $ request-> attribute1 "并且您将存储 c 而不是 b (您的期望值),它仍然会找到它并通过测试.
  1. Your URL is the one you want, without any typo or any errors
  2. The controller is doing what it is supposed to do, inserting data in this case.
  3. The controller is inserting the data you want it to insert. Let's say you have some processing behind curtains, here you can make sure that you sent "1 and 3" and it inserted "role X" (it is an example, let's say that would be your desired result after processing 1 and 3, so you are not directly inserting 1 and 3)
  4. always avoid asserting data from where you are testing it. In your case, you are using Request object, let's say it is your custom class, and you do something when you do $request->attribute1 = 2, so when you read it back as $request->attribute1 maybe you have done some process to store it and you have modified it... if you are asserting that without explicitly saying assert that attribute1 is what I expect you are never asserting it. If you have a mistake in your code and instead of returning b (1 = a, 2 = b, etc.) the code will always pass, because you have stored it as something else than expected, but you are asserting for what it has done (let's say that your mistake returned c instead of b) so you are saying "find $request->attribute1 in the database" and you will have stored c instead of b (your expected value) and it will still find it and pass the test.


除了 DB_DATABASE 或类似名称外,无需创建新的连接.在这种情况下,您只需在 .env.testing phpunit.xml 中定义该信息.


There is no need to create a new connection if it is the same except for DB_DATABASE or similar. In that case, you just define that info in .env.testing or in your phpunit.xml.

此外,无需执行<服务器名称="DB_CONNECTION";值=测试"/> < env name ="DB_CONNECTION"value ="testing"/.如果您看到Laravel GitHub的 phpunit.xml ,您将看到他们在5.7+上将< env> 更改为< server> ,因此请坚持使用与您的版本相对应的版本.虽然我现在不记得有一个区别,但是对于测试来说,没有问题.

Also, no need to do <server name="DB_CONNECTION" value="testing"/> and <env name="DB_CONNECTION" value="testing"/>. If you see Laravel GitHub's phpunit.xml, you will see that they changed <env> to <server> on 5.7+, so stick to the one that corresponds to your version. There is a difference though that I cannot remember now, but for testing, there is no problem.

因此,请确保已设置正确的 DB_HOST DB_PORT DB_USERNAME DB_PASSWORD .您可以具有相同的主机,但端口不同,或者您可以具有相同的主机和端口,但数据库名称不同,但用户名和密码相同.因此,请确保您连接到正确的数据库.

So, make sure you have set the right DB_HOST, DB_PORT, DB_USERNAME and DB_PASSWORD. You could have the same host but different port, or you could have same host and port but different database name, but same username and password. So make sure you are connecting to the correct database.

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

As your error is that it cannot find the desired table, clearly you are connecting to a database, so username and password should not be your problem, but the table does not exist.

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

One last important thing, are you using any trait on your tests ? There are some traits to automatically migrate the database and roll it back when finished, so there is no need for you to have your migrations sync manually in the testing environment. You should be using use RefreshDatabase; trait to do so.

最后一个提示,请尝试避免执行 DEF_SOMETHING ,因为:

Last tip, try to avoid doing DEF_SOMETHING because:

  1. 如果您的控制器与 Defi 相关,则无需说这是DEF数据",因此您可以直接执行某事.与数据库相同,如果表名是 cars ,请避免执行 car_wheels car_doors 等,请执行 wheels
  2. 避免执行 X_Y ,更喜欢执行 x_y ,这与数据库相同.始终坚持小写,对于数据库,始终坚持,但是对于模型的属性,始终坚持.(有关案件的更多信息)
  1. If your controller is related to Defi, there is no need to say "this is DEF data", we already know, so you can directly do something. Same for database, if table name is cars, avoid doing car_wheels, car_doors, etc., do wheels, doors, etc.
  2. Avoid doing X_Y, prefer to do x_y, same for database. Stick to lowercase always and, for database, stick to snake_case, but for models' attributes, always stick to camelCase. (more info about cases)

这篇关于测试数据库laravel 7.x的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆