Laravel - 使用SoftDeletes进行单元测试

时间:2017-06-28 10:40:33

标签: php mysql laravel unit-testing

我有一个基本测试,用于验证用户只能看到自己的帖子。

在我的test_database中,我发了几个帖子,用ModelFactory将其中一些帖子附加给用户 - 然后我测试该用户只能根据'user_id'列中的'user_id'列查看链接到用户的帖子。帖子记录。该测试基本上断言查询的输出是预期的。

  • 我在Post模型中使用SoftDeletes特性。
  • 我在Post Model上的'protected $ dates'属性中有'deleted_at'。

问题是'deleted_at'字段不会在factory() - > create()输出中返回 - 但它会出现在我获取所有用户帖子的查询中。

我能够通过将'deleted_at'字段添加到工厂并使用值null来解决这个问题,但是对于我来说,将此字段添加到每个工厂似乎很愚蠢。

为什么我明确需要为'deleted_at'执行此操作,但不是为'created_at'和'updated_at'执行此操作?

代码

发布架构

Schema::create('posts', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('company_id')->unsigned();
    $table->integer('locale_id')->unsigned();
    $table->string('name');
    $table->text('description')->nullable();
    $table->boolean('active')->default(false);
    $table->datetime('start_date')->nullable()->default(null);
    $table->datetime('end_date')->nullable()->default(null);

    $table->softDeletes();
    $table->timestamps();
});

发布工厂

$factory->define(App\Post::class, function (Faker\Generator $faker) {
    return [
        'company_id' => function () {
            return factory(App\Company::class)->create()->id;
        },
        'locale_id' => function () {
            return factory(App\Locale::class)->create()->id;
        },
        'title' => $faker->sentence(rand(1,3)),
        'body' => $faker->paragraph(1),
        'active' => rand(0,1),
        'start_date' => $faker->dateTimeBetween('now', '+2 years')->format('Y-m-d H:i:s'),
        'end_date' => $faker->dateTimeBetween('+2 years', '+4 years')->format('Y-m-d H:i:s')
    ];
});

我的单元测试

public function test_scope_foruser_only_returns_posts_for_authenticated_user()
{
    // Given there are 2 companies
    $companies = factory(Company::class, 2)->create();

    // With 1 post per company
    $postX = factory(Post::class)->create(['company_id' => $companies->first()->id]);
    $postY = factory(Post::class)->create(['company_id' => $companies->last()->id]);

    // Given I am logged in as user of the first company
    $user = factory(User::class)->create([
        'typeable_type' => Company::class,
        'typeable_id' => $companies->first()->id
    ]);

    // Login
    $this->be(User::first());

    // When I fetch the posts for User (via company)
    $posts = Post::forUser()->get()->toArray();


    // Then It returns only posts which the user's company
    // is associated with in a properly formatted array
    $this->assertCount(1, $posts);
    $this->assertEquals([$postX->toArray()], $posts);
}

这是应用于Post模型的查询范围,如上所示

public function scopeForUser($query)
{
    if ($company = auth()->user()->company) {
        return $query->where(['company_id' => $company->id]);
    }

    return $query;
}

0 个答案:

没有答案
相关问题