Laravel Testing: Unit, Feature ve Integration Test Rehberi
z
zafer ak
Yazar
28 November 2025
3 dakika okuma
2 görüntülenme
Laravel'de test yazımı: PHPUnit, Pest, mocking, factory'ler ve TDD yaklaşımı. Code coverage ve CI entegrasyonu.
Neden Test Yazmalıyız?
- Bug'ları erken yakala
- Refactoring güvenliği
- Documentation görevi
- Daha iyi kod tasarımı (TDD)
Test Türleri
Unit Tests
Tek bir class/method test eder. Bağımlılıklar mock'lanır.
// tests/Unit/Services/PriceCalculatorTest.php
class PriceCalculatorTest extends TestCase
{
public function test_calculates_discount_correctly()
{
$calculator = new PriceCalculator();
$result = $calculator->applyDiscount(100, 20);
$this->assertEquals(80, $result);
}
}
Feature Tests
HTTP request/response test eder.
// tests/Feature/UserRegistrationTest.php
class UserRegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_register()
{
$response = $this->post('/register', [
'name' => 'John Doe',
'email' => '[email protected]',
'password' => 'password',
'password_confirmation' => 'password',
]);
$response->assertRedirect('/dashboard');
$this->assertDatabaseHas('users', [
'email' => '[email protected]'
]);
}
}
PHPUnit Assertions
$this->assertTrue($value);
$this->assertFalse($value);
$this->assertEquals($expected, $actual);
$this->assertCount(3, $array);
$this->assertNull($value);
$this->assertInstanceOf(User::class, $user);
$this->assertArrayHasKey('name', $array);
HTTP Testing
// GET request
$response = $this->get('/users');
$response->assertStatus(200);
$response->assertJson(['data' => []]);
// POST with authentication
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/posts', ['title' => 'Test']);
$response->assertStatus(201);
// API testing
$response = $this->postJson('/api/users', $data);
$response->assertCreated()
->assertJsonStructure(['id', 'name', 'email']);
Database Testing
use RefreshDatabase; // Her testte DB reset
// Assertions
$this->assertDatabaseHas('users', ['email' => '[email protected]']);
$this->assertDatabaseMissing('users', ['email' => '[email protected]']);
$this->assertDatabaseCount('users', 5);
$this->assertSoftDeleted('users', ['id' => 1]);
Factories
// database/factories/UserFactory.php
class UserFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'password' => bcrypt('password'),
];
}
public function admin(): static
{
return $this->state(['role' => 'admin']);
}
}
// Kullanım
$user = User::factory()->create();
$users = User::factory()->count(10)->create();
$admin = User::factory()->admin()->create();
Mocking
// External service mock
$this->mock(PaymentGateway::class, function ($mock) {
$mock->shouldReceive('charge')
->once()
->with(100)
->andReturn(true);
});
// Facade mock
Mail::fake();
// ... kod çalıştır
Mail::assertSent(WelcomeEmail::class);
// Event fake
Event::fake([OrderCreated::class]);
// ... kod çalıştır
Event::assertDispatched(OrderCreated::class);
Pest (Modern Syntax)
// tests/Feature/UserTest.php
test('user can view profile', function () {
$user = User::factory()->create();
$this->actingAs($user)
->get('/profile')
->assertOk()
->assertSee($user->name);
});
it('requires authentication', function () {
$this->get('/dashboard')
->assertRedirect('/login');
});
Testleri Çalıştırma
# Tüm testler
php artisan test
# Specific test
php artisan test --filter=UserRegistrationTest
# Coverage raporu
php artisan test --coverage
# Parallel testing
php artisan test --parallel
Sonuç
Test yazmak başlangıçta zaman alır ama uzun vadede hataları azaltır ve geliştirme hızını artırır. TDD ile başlayın!