前2篇,我們探討了「網站文章」的情境題;今明兩天,就讓我們探討另一個情境題「會員註冊」吧!
這邊我們同樣假設網站是採前後端分離的設計,因此我們就專注在測試 API 的部分,不過會多一個「註冊驗證信」的部分要實作與做測試驗證。
這邊我們使用驗證時間來取代驗證狀態,並以有無驗證時間來判斷是否已驗證
依據以上的使用案例,我們可規畫出以下 API / 功能:
POST /registers
GET /users/{id}/validation?token={token}
接著就來實作 API 與註冊驗證信的邏輯吧!
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration{
/** * Run the migrations. * * @return void */
public function up() {
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('verify_email_token', 128)->nullable();
$table->rememberToken();
$table->timestamps();
}); } /** * Reverse the migrations. * * @return void */
public function down() {
Schema::dropIfExists('users');
}};
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable{
use HasApiTokens, HasFactory, Notifiable;
/** * The attributes that are mass assignable. * * @var array<int, string> */
protected $fillable = [
'name',
'email',
'password',
'email_verified_at',
'verify_email_token',
]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */
protected $hidden = [
'password',
'remember_token',
]; /** * The attributes that should be cast. * * @var array<string, string> */
protected $casts = [
'email_verified_at' => 'datetime',
];}
<?php
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::post('/register', [UserController::class, 'register'])
->name('register');
Route::get('/verify-user-email', [UserController::class, 'verifyUserEmail'])
->name('verify-user-email');
<?php
namespace App\Http\Controllers;
use App\Mail\VerifyUserMail;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
class UserController extends Controller{
public function register(Request $request) {
$request->validate([
'name' => 'required',
'email' => 'required',
'password' => 'required',
]); $user = User::create([
'name' => $request->input('name'),
'email' => $request->input('email'),
'password' => Hash::make($request->input('password')),
'verify_email_token' => Str::random(128),
]); Mail::to($user->email)
->send(new VerifyUserMail($user));
return response()->json('');
} public function verifyUserEmail(Request $request) {
$request->validate([
'token' => 'required',
]); $token = $request->input('token');
$user = User::where('verify_email_token', $token)->first();
if (empty($user)) {
return response('Failed', 404);
} $user->email_verified_at = now();
$user->save();
return response('Success');
}}
<?php
namespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class VerifyUserMail extends Mailable{
use Queueable, SerializesModels;
private $user;
/** * Create a new message instance. * * @return void */
public function __construct(User $user) {
$this->user = $user;
} /** * Build the message. * * @return $this */
public function build() {
$data = [
'verifyLink' => route('verify-user-email', ['token' => $this->user->verify_email_token]),
]; return $this->with($data)
->view('view.mail.verify-email');
}}
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Verify Mail</title>
</head>
<body class="antialiased">
<a href="{{ $verifyLink }}">Verify Your Email</a>
</body>
</html>
這邊我們要準備的是User 的 Factory 類別:
<?php
namespace Database\Factories;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory{
/** * Define the model's default state. * * @return array */
public function definition(): array {
return [
'name' => $this->faker->name,
'email' => $this->faker->safeEmail,
'password' => bcrypt($this->faker->password),
'remember_token' => Str::random(10),
'verify_email_token' => Str::random(128),
]; }
到這邊為止,我們已經把測試目標準備好了,下一篇我們就來針對各使用案例來寫測試吧!
如果您喜歡這篇文章,歡迎加入追蹤以接收新文章通知 😄