【问题标题】:General error: 1 no such table: App\Models\ModelName while testing laravel一般错误:1 no such table: App\Models\ModelName while testing laravel
【发布时间】:2021-11-26 18:49:40
【问题描述】:

我的测试:

class FloorStackTest extends TestCase
{
    use RefreshDatabase, WithFaker, DatabaseMigrations;
    protected $endPoint = '/endpoint';

    public function test_unit_type_note_added_successfully()
    {
        $this->signIn();
        $this->withoutExceptionHandling();
        $unitType = UnitType::factory()->create();
        $note = $this->faker()->sentence(3);
        $resp = $this->ajaxPost($this->admin_route.$this->endPoint."/".$unitType->property_version_id."/save-ut-note",[
            'notes' => [
                [
                    "ut_note_id" => "utn_".$unitType->id,
                    "note" => $note
                ]
            ]
        ])->assertStatus(Response::HTTP_OK);
        $results = [
            'notes'         => $note
        ];


        //i could print upto here
        dd('hit');

        $this->assertDatabaseHas(UnitType::class,$results);

        //but could not print here
        dd('hit');
        
    }
}

我使用sqlite 进行测试,我使用的是 laravel 8(之前是从 laravel 5 更新的,以防万一确认)

我上面的代码,你可以看到我可以print hit的点。

我正在使用.env.testing

DB_CONNECTION=sqlite
DB_DATABASE="database/test.sqlite"
DB_FOREIGN_KEYS=false

我已经在使用:use RefreshDatabase,但它仍然显示错误。完整的错误是:

Tests\Feature\FloorStackTest::test_unit_type_note_added_successfully
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 no such table: App\Models\UnitType (SQL: select count(*) as aggregate from "App\Models\UnitType" where ("notes" = Eveniet incidunt consequuntur dolore est.))

我的模特UnitType 有这个

    use SoftDeletes, HasFactory;
    protected $table = 'unit_types';

    protected $guarded = ['id'];
    protected $dates = ['created_at','updated_at','deleted_at'];

【问题讨论】:

    标签: laravel laravel-testing


    【解决方案1】:

    首先,请注意,将模型或完全限定的类名传递给 assertDatabaseHas 方法仅在框架版本 8 中可用。请参阅下面的签名更改:

    Signature in v7:protected $this assertDatabaseHas(string $table, array $data, string|null $connection = null).

    Signature in v8:protected $this assertDatabaseHas(Model|string $table, array $data, string|null $connection = null).

    最终,必须使用实际的表名进行断言。这就是它在文档中的演示方式:

    $this->assertDatabaseHas('users', [
        'email' => 'sally@example.com',
    ]);
    

    所以如果你使用 Laravel

    $this->assertDatabaseHas('unit_types', $results);
    

    作为替代方案,取自 this answer,您仍然可以使用模型类来获取表名,而不是对字符串进行硬编码。

    类似这样的:

    $this->assertDatabaseHas((new UnitType)->getTable(), $results);
    

    在 Laravel 8 中,该方法将接受一个模型,并通过该方法运行它以获取表名:

    protected function getTable($table)
    {
        return is_subclass_of($table, Model::class) ? (new $table)->getTable() : $table;
    }
    

    这里的table 可以是模型实例,也可以是完全限定的类名(new UnitType,或UnitType::class)。请注意,它必须扩展基类 Model 才能让 Laravel 正确解析它,否则它只会将类名字符串传递给查询。

    【讨论】:

    • 我不确定,因为在另一个项目中我一直在使用 Model::class 并且运行良好。
    • UnitType 是否扩展 Model?看起来确实有用于传递模型的未记录功能,我将更新我的答案以包含它,但您可能应该更新您的问题以包含更多模型代码。
    • 我明白了,尽管它是 laravel 8,但它似乎面临相同的表问题,它不接受类模型,而是使用“表名”。可能是它没有正确更新,但现在我面临这个新问题:General error: 1 no such table: migrations (SQL: select max("batch") as aggregate from "migrations")
    • 我不知道这是否是原因,但您可能不应该在测试中同时使用 RefreshDatabaseDatabaseMigrations 特征。他们完成同样的事情,并且可能相互冲突。 RefreshDatabase 在大多数情况下是更可取的,因为它将决定是否需要运行迁移或仅回滚事务。
    猜你喜欢
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2018-05-24
    • 2022-07-06
    • 2020-04-26
    • 1970-01-01
    相关资源
    最近更新 更多