Laravel 单元测试,如何“seeInDatabase”软删除行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33117746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 12:30:06  来源:igfitidea点击:

Laravel Unit Testing, how to "seeInDatabase" soft deleted row?

phpunit-testinglaraveltestinglaravel-5

提问by Matt Komarnicki

I'm working on a small unit test where I soft delete a row. To mark the test as successful I have to find that row with:

我正在做一个小单元测试,我软删除一行。要将测试标记为成功,我必须找到该行:

  • a given ID and
  • deleted_atcolumn should not benull.
  • 给定的 ID 和
  • deleted_at不应为空。

I can fulfill first condition - because obviously I know the ID.

我可以满足第一个条件 - 因为显然我知道 ID。

Unfortunately I don't know how to tell seeInDatabasemethod that I expect deleted_atnot to benull:

不幸的是,我不知道如何告诉seeInDatabasedeleted_at不希望为null 的方法:

$this->seeInDatabase(
       'diary_note_categories',
       [
           'id' => 'a7e35ad0-6f00-4f88-b953-f498797042fc',
           'deleted_at' => null // should be is not null, like <> or != or whatever
       ]
 );

Any hints?

任何提示?

'deleted_at <>' => nullbreaks

'deleted_at <>' => null休息

'deleted_at' => ['!=' => null]breaks as well

'deleted_at' => ['!=' => null]也休息

回答by Wojciech Mruk

I did it in this way:

我是这样做的:

$this->seeInDatabase('diary_note...',['id' => 'a7e35ad0'])
->notSeeInDatabase('diary_note...',['id' => 'a7e35ad0','deleted_at'=>null]);

So I'm checking in two steps

所以我分两步检查

  1. I check if there is a record with our id in the table
  2. I check if there is no record with our id and deleted_at = null in the table
  1. 我检查表中是否有我们 id 的记录
  2. 我检查表中是否没有我们的id和deleted_at = null的记录

回答by EspadaV8

It's not currently possible. Both seeInDatabaseand notSeeInDatabasejust pass the array directly to the wheremethod of the query builder and that doesn't understand how to deal with anything other than =when passed an array.

目前是不可能的。双方seeInDatabasenotSeeInDatabase只需直接将数组传递给where查询生成器的方法,并且不知道如何处理以外的任何=时候通过一个数组。

https://github.com/laravel/framework/blob/2b4b3e3084d3c467f8dfaf7ce5a6dc466068b47d/src/Illuminate/Database/Query/Builder.php#L452

https://github.com/laravel/framework/blob/2b4b3e3084d3c467f8dfaf7ce5a6dc466068b47d/src/Illuminate/Database/Query/Builder.php#L452

public function where($column, $operator = null, $value = null, $boolean = 'and')
{
    // If the column is an array, we will assume it is an array of key-value pairs
    // and can add them each as a where clause. We will maintain the boolean we
    // received when the method was called and pass it into the nested where.
    if (is_array($column)) {
        return $this->whereNested(function ($query) use ($column) {
            foreach ($column as $key => $value) {
                $query->where($key, '=', $value);
            }
        }, $boolean);
    }

    // ...
}

Option 1 - Add the following code to your TestCase class which you extend your test cases from

选项 1 - 将以下代码添加到您的 TestCase 类中,您可以从中扩展测试用例

Gist: https://gist.github.com/EspadaV8/73c9b311eee96b8e8a03

要点:https: //gist.github.com/EspadaV8/73c9b311eee96b8e8a03

<?php
/**
 * Assert that a given where condition does not matches a soft deleted record
 *
 * @param  string $table
 * @param  array  $data
 * @param  string $connection
 * @return $this
 */
protected function seeIsNotSoftDeletedInDatabase($table, array $data, $connection = null)
{
    $database = $this->app->make('db');

    $connection = $connection ?: $database->getDefaultConnection();

    $count = $database->connection($connection)
        ->table($table)
        ->where($data)
        ->whereNull('deleted_at')
        ->count();

    $this->assertGreaterThan(0, $count, sprintf(
        'Found unexpected records in database table [%s] that matched attributes [%s].', $table, json_encode($data)
    ));

    return $this;
}

/**
 * Assert that a given where condition matches a soft deleted record
 *
 * @param  string $table
 * @param  array  $data
 * @param  string $connection
 * @return $this
 */
protected function seeIsSoftDeletedInDatabase($table, array $data, $connection = null)
{
    $database = $this->app->make('db');

    $connection = $connection ?: $database->getDefaultConnection();

    $count = $database->connection($connection)
        ->table($table)
        ->where($data)
        ->whereNotNull('deleted_at')
        ->count();

    $this->assertGreaterThan(0, $count, sprintf(
        'Found unexpected records in database table [%s] that matched attributes [%s].', $table, json_encode($data)
    ));

    return $this;
}

Option 2 - Install the following composer package

选项 2 - 安装以下 composer 包

This composer package is the exact same code as above, but packaged up for Composer.

这个 composer 包与上面的代码完全相同,但是是为 Composer 打包的。

composer require kirkbater/soft-deletes

composer require kirkbater/soft-deletes

Then use it inside of your specific test class:

然后在您的特定测试类中使用它:

<?php

use Kirkbater\Testing\SoftDeletes;

class MyTestClass extends TestClass {

    use SoftDeletes;

}

回答by GluePear

This is an old question, but for those using more recent versions of Laravel (5.4 and above), there is now an assertSoftDeletedassertion: documentation.

这是一个老问题,但对于那些使用更新版本的 Laravel(5.4 及更高版本)的人来说,现在有一个assertSoftDeleted断言:文档

So the answer to the original question would now be:

所以原来问题的答案现在是:

$this->assertSoftDeleted('diary_note_categories', [
    'id' => 'a7e35ad0-6f00-4f88-b953-f498797042fc'
]);

回答by fico7489

It is not tested, but try like this :

它没有经过测试,但可以这样尝试:

$this->seeInDatabase(
       'diary_note_categories',
       [
           'id' => 'a7e35ad0-6f00-4f88-b953-f498797042fc',
           'deleted_at' => ['deleted_at' ,'!=', null ] // should be is not null, like <> or != or whatever
       ]
 );