44.消息通知测试重构
- 本系列文章为
laracasts.com
的系列视频教程 ——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版 ;- 视频源码地址:github.com/laracasts/Lets-Build-a-...;
- 本项目为一个 forum(论坛)项目,与本站的第二本实战教程 《Laravel 教程 - Web 开发实战进阶》 类似,可互相参照。
本节说明#
- 对应视频教程第 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);
}
}
测试一下:
我们在 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()));
现在我们去数据库看一下:
现在我们知道该如何定义模型了。请记住,我们是为了测试而来定义模型工厂,所以我们尽可以放心地进行一些 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);
});
}
}
运行测试:
Good luck!下一节,我们将未读消息显示出来。
推荐文章: