今回はLaravelでSlack通知の実装方法、およびそのSlack通知のテストコードの書き方について解説します。
Slack通知の実装方法
Slack WebHookURLの取得
まず、SlackのWebHookURLを取得します。
以下の記事を参考に取得してください。(とてもわかりやすく書かれています)
Slack関連情報を.envに登録
WebHookURLが取得できたら.envに書き込みます。
// 取得したWebHookURL
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxxxxxxxxx/xxxxxxxxxx/xxxxxxxxxxxxxxxxxxx
// 通知を送信するチャンネル
SLACK_CHANNEL=#general
// 通知の送信者名
SLACK_SENDER_NAME=Slack-Notification-Bot
// 通知の送信者アイコン画像のURL
SLACK_ICON=https://s3-us-west-2.amazonaws.com/xxxxxxx/xxxxxx/xxxxxx/xxxxxxxx.png
Slack通知チャンネルの追加
Slack通知チャンネルを追加するためにcomposerパッケージをインストールします。
> composer require laravel/slack-notification-channel
Notificationクラスの作成
以下のコマンドでNotificationクラスを作成します。
> php artisan make:notification SlackNotification
app/Notifications/SlackNotification.php
というファイルが作成されますが、コードがメール通知の内容になっていますので、これを以下のようにSlack通知向けの内容に変更します。
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\SlackMessage;
class SlackNotification extends Notification
{
use Queueable;
protected $channel;
protected $icon;
protected $name;
protected $message;
/**
* Create a new notification instance.
* @return void
*/
public function __construct($message)
{
// Slackに関数する情報はconfigに定義しておく
$this->channel = config('slack.channel');
$this->icon = config('slack.icon');
$this->name = config('slack.sender_name');
$this->message = $message;
}
/**
* Get the notification's delivery channels.
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['slack'];
}
/**
* Get the array representation of the notification.
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [];
}
/**
* Get the Slack representation of the notification.
* @param mixed $notifiable
* @return SlackMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->from($this->name)
->image($this->icon)
->to($this->channel)
->content($this->message);
}
}
__construct
内でメンバ変数に代入する値は以下のようにconfigに設定しておきます。
<?php
return [
'webhook_url' => env('SLACK_WEBHOOK_URL'),
'channel' => env('SLACK_CHANNEL'),
'sender_name' => env('SLACK_SENDER_NAME'),
'icon' => env('SLACK_ICON'),
];
サービスコンテナの作成
サービスコンテナを利用してSlack通知処理の実装をしていきます。
まず、Slack通知処理を記述するサービスコンテナを作成し以下のように変更します。
<?php
namespace App\Services;
use Illuminate\Notifications\Notifiable;
use App\Notifications\SlackNotification;
class SlackNotificationService implements SlackNotificationServiceInterface
{
use Notifiable;
public function send($message)
{
$this->notify(new SlackNotification($message));
}
protected function routeNotificationForSlack()
{
return config('slack.webhook_url');
}
/**
* Get the value of the notifiable's primary key.
* ※後述するテストで必要(ないとエラーになる)
*
* @return mixed
*/
public function getKey()
{
//
}
}
作成したサービスコンテナと結合させるインターフェースを作成し以下のように変更します。
<?php
namespace App\Services;
interface SlackNotificationServiceInterface
{
public function send($message);
}
作成したサービスコンテナとインターフェースを以下のように結合します。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\SlackNotificationServiceInterface;
use App\Services\SlackNotificationService;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
* @return void
*/
public function register()
{
$this->app->singleton(
SlackNotificationServiceInterface::class,
SlackNotificationService::class
);
}
}
サービスコンテナの作成は以上です。
Slack通知の送信
作成したサービスコンテナを利用する方法は、下記のようにSlackNotificationServiceInterface
をコンストラクタインジェクションした上で、send
関数を呼び出すだけです!
これだけでSlack通知の送信ができます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\SlackNotificationServiceInterface;
class SampleController extends Controller
{
/**
* @var SlackNotificationServiceInterface
*/
private $slack_notification_service_interface;
/**
* @param SlackNotificationServiceInterface $slack_notification_service_interface
*/
public function __construct(
SlackNotificationServiceInterface $slack_notification_service_interface,
) {
$this->slack_notification_service_interface = $slack_notification_service_interface;
}
/**
* Slack通知を送信する
*/
public function sendSlackNotification()
{
$this->slack_notification_service_interface->send('こんにちは!!');
}
}
↓のようにしっかりSlack通知が送信されています。

Slack通知の実装方法は以上です。
Slack通知のテストコード
上で作成したSlack通知機能のテストコードを実装します。
namespace Tests\Controllers;
use Tests\TestCase;
use App\Notifications\SlackNotification;
use App\Services\SlackNotificationService;
use Illuminate\Support\Facades\Notification;
class SampleControllerTest extends TestCase
{
public function testsendSlackNotification()
{
/**
* sendSlackNotificationのテスト
*
* @return void
*/
public function testSendSlackNotification()
{
$expected_message = 'こんにちは!!';
// Slack通知が実際に送信されないようにする
Notification::fake();
// Slack通知の送信回数が1回かのテスト(第3引数の数値が期待する送信回数)
Notification::assertSentToTimes(new SlackNotificationService, SlackNotification::class, 1);
// Slack通知に記載されている内容をテスト
Notification::assertSentTo(
new SlackNotificationService,
SlackNotification::class,
// 第一引数の$notificationはSlackNotification::classのインスタンス
function ($notification, $channels) use ($expected_message) {
// ReflectionClassのインスタンスを作成
$reflected_notification = new \ReflectionClass($notification);
// $notificationのmessageプロパティを取得
$message_property = $reflected_notification->getProperty('message');
// messageプロパティへのアクセスを許可
$message_property->setAccessible(true);
// messageプロパティの値(Slack通知に記載されている内容)を取得する
$message = $message_property->getValue($notification);
// messageプロパティの値が期待するメッセージと同じかをテストする
$this->assertEquals($expected_message, $message);
// 最後にtrueを返さないとエラーになる
// (return $expected_message === $message; でもOK)
return true;
}
);
}
}
}
上のテストコードを解説します。
Notification::fake();
とすることで、テスト実行時はSlack通知が送信されなくなります。(テストを実行する度に毎回Slack通知が送信されたら鬱陶しいですからね。笑)
Notification::assertSentToTimes(new SlackNotificationService, SlackNotification::class, 1)
;ではSlack通知の送信回数が1回かをテストしています。
第3引数を2とすればSlack通知が2回送信されていることをテストします。
※Slack通知が送信されていないこと(送信回数が0回)をテストしたい場合は、Notification::assertNothingSent();
でテストすることができます。
Notification::assertSentTo
ではSlack通知に記載されている内容をテストしています。
Slack通知に記載されている内容をテストするためにはSlackNotification
クラスのmessage
プロパティへアクセスする必要がありますが、message
プロパティのアクセス修飾子はprotectedのため、普通の方法ではアクセスできません。
そのため、第3引数のコールバック関数でリフレクションクラスのインスタンスを作成し、message
プロパティへのアクセスを許可する必要があります。
アクセスを許可することでmessage
プロパティの値を取得でき、Slack通知に記載された内容がテストできるようになります。
Slack通知のテスト方法は以上です。
参考
【PHP】リフレクションクラスでprivate変数、privateメソッドをテストする