#28 Laravel基礎
ユニットテストとモック
ユニットテストとは
ユニットテスト? 個々のクラスやメソッドを独立して検証するテスト。外部依存を切り離してロジック単体が正しく動くかを確認する。 は、特定のクラスやメソッドを外部依存なしで単独テストする手法です。DBやメール送信など副作用のある処理は モック? テスト中に本物のクラスの代わりに使う偽物オブジェクト。メール送信やAPI呼び出しなど副作用のある処理を置き換えてテストできる。 (偽物オブジェクト)で置き換えます。
ユニットテストを作る
php artisan make:test PostServiceTest --unit
tests/Unit/PostServiceTest.php が生成されます。
<?php
// 📁 tests/Unit/PostServiceTest.php
namespace Tests\Unit;
use App\Services\PostService;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PostServiceTest extends TestCase
{
use RefreshDatabase;
public function test_スラッグを正しく生成できる(): void
{
$service = new PostService();
// タイトルからスラッグを生成するメソッドをテスト
$slug = $service->generateSlug('Laravel入門 基礎編');
$this->assertEquals('laravel-nyuumon-kiso-hen', $slug);
}
}
Laravelのモック
Laravelには Mail, Notification, Storage, Queue などのFacadeをモック化するヘルパーが用意されています。
Mail のモック
// 📁 tests/Feature/RegisterTest.php
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeMail;
public function test_登録するとウェルカムメールが送信される(): void
{
// メールの実際の送信を止める
Mail::fake();
$response = $this->post('/register', [
'name' => 'テストユーザー',
'email' => 'test@example.com',
'password' => 'password123',
'password_confirmation' => 'password123',
]);
// WelcomeMail が送信されたことを確認
Mail::assertSent(WelcomeMail::class);
// 特定のアドレスに送られたか確認
Mail::assertSent(WelcomeMail::class, function ($mail) {
return $mail->hasTo('test@example.com');
});
}
Notification のモック
use Illuminate\Support\Facades\Notification;
use App\Notifications\CommentPosted;
public function test_コメントを投稿すると通知が送信される(): void
{
Notification::fake();
$user = User::factory()->create();
$post = Post::factory()->create(['user_id' => $user->id]);
$this->actingAs(User::factory()->create())
->post("/posts/{$post->id}/comments", ['body' => 'テストコメント']);
Notification::assertSentTo($user, CommentPosted::class);
}
Queue のモック
use Illuminate\Support\Facades\Queue;
use App\Jobs\SendDailyReport;
public function test_レポートジョブがキューに追加される(): void
{
Queue::fake();
$this->post('/admin/report/send');
Queue::assertPushed(SendDailyReport::class);
}
Storage のモック
use Illuminate\Support\Facades\Storage;
public function test_サムネイルをアップロードして保存できる(): void
{
Storage::fake('public'); // fakeディスクを使う
$user = User::factory()->create();
$file = \Illuminate\Http\UploadedFile::fake()->image('thumbnail.jpg', 800, 600);
$response = $this->actingAs($user)->post('/posts', [
'title' => 'テスト投稿',
'body' => 'テスト本文',
'thumbnail' => $file,
]);
// ファイルが保存されたことを確認
Storage::disk('public')->assertExists('thumbnails/' . $file->hashName());
}
Mockeryでクラスをモックする
外部APIクライアントなどを差し替える場合は Mockery を使います。
// 📁 tests/Feature/PaymentTest.php
use App\Services\PaymentGateway;
use Mockery;
public function test_支払いが完了すると注文が確定する(): void
{
// PaymentGateway の偽物を作る
$mockGateway = Mockery::mock(PaymentGateway::class);
$mockGateway->shouldReceive('charge')
->once()
->with(5000)
->andReturn(['status' => 'success', 'transaction_id' => 'txn_123']);
// サービスコンテナに偽物を登録
$this->app->instance(PaymentGateway::class, $mockGateway);
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/checkout', ['amount' => 5000]);
$response->assertRedirect('/orders/complete');
$this->assertDatabaseHas('orders', ['status' => 'paid']);
}
テストヘルパーとユーティリティ
// 時間を固定する
\Illuminate\Support\Carbon::setTestNow('2025-01-01 12:00:00');
// テスト終了後に元に戻す
\Illuminate\Support\Carbon::setTestNow();
// イベント発火を確認
\Illuminate\Support\Facades\Event::fake();
Event::assertDispatched(\App\Events\UserRegistered::class);
// HTTPクライアントのモック(外部APIのテスト)
\Illuminate\Support\Facades\Http::fake([
'api.example.com/*' => Http::response(['status' => 'ok'], 200),
]);
まとめ
Mail::fake(),Notification::fake(),Queue::fake()でFacadeをモックできるStorage::fake('disk')でファイル操作をテストできる- Mockery でサービスクラスを差し替えてテストできる
Carbon::setTestNow()で時刻を固定できる
次回はEloquentの便利なコレクションメソッドを学びます。