[Laravel]メール確認の単体テスト

[Laravel]メール確認の単体テスト


環境

Ubuntu 18.04(WSL)

Laravel 5.8

VerifiesEmailsトレイトのverify()メソッドをVerificationControllerでオーバーライドしたので単体テストが必要になりました。


Controllers/Auth/VerificationController.php

protected $redirectTo = '/';

public function verify(Request $request)
{
if ($request->route('id') == $request->user()->getKey() && $request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect($this->redirectPath())->with('my_status', __('Registration completed.'));
}


メール確認に成功するとトップページにリダイレクトして

Registration completed.というフラッシュメッセージを表示します。

メール確認は/email/verify/{id}?expires=xxxxx&signature=xxxxxにGETまたはHEADでリクエストを送ると成功します。

{id}はメール確認をするユーザーのIDです。

expiresとsignatureがついたURLをどうやって作っているかは

/vendor/laravel/framework/src/Illuminate/Auth/Notifications.phpに書いてあります。


/vendor/laravel/framework/src/Illuminate/Auth/Notifications.php

/**

* Get the verification URL for the given notifiable.
*
* @param mixed $notifiable
* @return string
*/

protected function verificationUrl($notifiable)
{
return URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
['id' => $notifiable->getKey()]
);
}

URL::temporarySignedRoute()を使えばいい事が分かりました。

第一引数はルーティングの名前、第二引数はexipiresの数字、第三引数はemail/verify/{id}{id}に入れる文字列が値に入った配列です。


参考


単体テストのコード


/tests/Unit/VerificationControllerTest.php

<?php

namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\User;
use Illuminate\Support\Carbon;

class VerificationControllerTest extends TestCase
{
use RefreshDatabase;

/**
* A basic unit test example.
*
* @return void
*/

public function testExample()
{
$user = factory(User::class)->create(
['email_verified_at' => null]
);

$response = $this->actingAs($user)
->get(\URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(\Config::get('auth.verification.expire', 60)),
['id' => $user->id]
))
->assertRedirect('/');
}
}