Menu

44.消息通知测试重构

本节说明

  • 对应视频教程第 44 小节:Test Refactoring

本节内容

本节我们先来对NotificationsTest测试文件进行下重构。对于本文件中的所有测试而言,用户必须登录,所以我们可以将$this->signIn();代码抽取到setUp方法中:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;

class NotificationsTest extends TestCase
{
    use DatabaseMigrations;

    public function setUp()
    {
        parent::setUp();

        $this->signIn();
    }

    /** @test */
    public function a_notification_is_prepared_when_a_subscribed_thread_receives_a_new_reply_that_is_not_by_the_current_user()
    {
        $thread = create('App\Thread')->subscribe();

        $this->assertCount(0,auth()->user()->notifications);

        $thread->addReply([
           'user_id' => auth()->id(),
           'body' => 'Some reply here'
        ]);

        $this->assertCount(0,auth()->user()->fresh()->notifications);

        $thread->addReply([
            'user_id' => create('App\User')->id,
            'body' => 'Some reply here'
        ]);

        $this->assertCount(1,auth()->user()->fresh()->notifications);
    }

    /** @test */
    public function a_user_can_fetch_their_unread_notifications()
    {
        $thread = create('App\Thread')->subscribe();

        $thread->addReply([
            'user_id' => create('App\User')->id,
            'body' => 'Some reply here'
        ]);

        $user = auth()->user();

        $response =  $this->getJson("/profiles/" . $user->name . "/notifications")->json();

        $this->assertCount(1,$response);
    }

    /** @test */
    public function a_user_can_clear_a_notification()
    {
        $thread = create('App\Thread')->subscribe();

        $thread->addReply([
            'user_id' => create('App\User')->id,
            'body' => 'Some reply here'
        ]);

        $user = auth()->user();

        $this->assertCount(1, $user->unreadNotifications);

        $notificationId = $user->unreadNotifications->first()->id;

        $this->delete("/profiles/" . $user->name . "/notifications/{$notificationId}");

        $this->assertCount(0, $user->fresh()->unreadNotifications);
    }
}

测试一下:
file
我们在 3 个测试中,为了触发消息通知都使用了以下代码:

$thread = create('App\Thread')->subscribe();

$thread->addReply([
    'user_id' => create('App\User')->id,
    'body' => 'Some reply here'
]);

在通常的做法中,我们会把以上代码抽取成一个共用的方法,但是在我们的测试中,我们只需要确保有消息通知即可。我们利用 模型工厂 来填充数据:当需要通知消息时,我们填充 1 条数据即可。我们在模型工厂文件中定义模型:
forum\database\factories\ModelFactory.php

.
.
$factory->define(Illuminate\Notifications\DatabaseNotification::class,function ($faker){
    return [

    ];
});

我们不太清楚模型的定义,但是没关系,让我们进入Tinker环境,生成 1 条真实数据:

$ php artisan tinker
>>> App\User::first()->notify(new App\Notifications\ThreadWasUpdated(App\Thread::first(),App\Reply::first()));

现在我们去数据库看一下:
file
现在我们知道该如何定义模型了。请记住,我们是为了测试而来定义模型工厂,所以我们尽可以放心地进行一些 Hard Coding
forum\database\factories\ModelFactory.php

.
.
$factory->define(Illuminate\Notifications\DatabaseNotification::class,function ($faker){
    return [
        'id' => Ramsey\Uuid\Uuid::uuid4()->toString(),
        'type' => 'App\Notifications\ThreadWasUpdated',
        'notifiable_id' => function (){
            return auth()->id() ?: factory('App\User')->create()->id;
        },
        'notifiable_type' => 'App\User',
        'data' => ['foo' => 'bar']
    ];
});

现在我们可以对我们的测试进行全面的修改:
forum\tests\Feature\NotificationsTest.php

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Notifications\DatabaseNotification;
use Tests\TestCase;

class NotificationsTest extends TestCase
{
    use DatabaseMigrations;

    public function setUp()
    {
        parent::setUp();

        $this->signIn();
    }

    /** @test */
    public function a_notification_is_prepared_when_a_subscribed_thread_receives_a_new_reply_that_is_not_by_the_current_user()
    {
        $thread = create('App\Thread')->subscribe();

        $this->assertCount(0,auth()->user()->notifications);

        $thread->addReply([
           'user_id' => auth()->id(),
           'body' => 'Some reply here'
        ]);

        $this->assertCount(0,auth()->user()->fresh()->notifications);

        $thread->addReply([
            'user_id' => create('App\User')->id,
            'body' => 'Some reply here'
        ]);

        $this->assertCount(1,auth()->user()->fresh()->notifications);
    }

    /** @test */
    public function a_user_can_fetch_their_unread_notifications()
    {
        create(DatabaseNotification::class);

        $this->assertCount(
            1,
            $this->getJson("/profiles/" . auth()->user()->name . "/notifications")->json()
        );
    }

    /** @test */
    public function a_user_can_clear_a_notification()
    {
        create(DatabaseNotification::class);

        tap(auth()->user(),function ($user) {
            $this->assertCount(1, $user->unreadNotifications);

            $this->delete("/profiles/" . $user->name . "/notifications/" . $user->unreadNotifications->first()->id);

            $this->assertCount(0, $user->fresh()->unreadNotifications);
        });
    }
}

运行测试:
file
Good luck!下一节,我们将未读消息显示出来。

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 0
发起讨论


暂无话题~
刻意练习,每日精进。
1
点赞
48
浏览
0
讨论

维护者