CodeBlanks Logo Icon CodeBlanks

Test doubles (mock, stub)

PHP kursu · İleri seviye · Ders 78/92

Bağımlılıkları izole etmek için mock ve stub kullanmayı öğrenirsin.

Test double nedir?

Bazı sınıflar dış servislere bağımlıdır: veritabanı, e-posta, ödeme. Bunları her testte çağırmak yavaş ve kırılgandır. Test double, bu bağımlığın sahte bir sürümüdür; gerçek yan etkiler olmadan testin hızlı ve öngörülebilir olmasını sağlar. PHPUnit'de getMockBuilder ile oluşturulur: $this->getMockBuilder(PaymentGateway::class)->getMock(). Stub yalnızca sabit yanıt döner; Mock çağrıların yapılıp yapılmadığını da denetler.

Stub ve mock farkı

Stub, çağrılana önceden belirlenmiş yanıt döner: $stub->method('charge')->willReturn(true). İçten çok, çağrıldığını umursamaz. Mock ise çağrıların yapılıp yapılmayacağını da bekler: $mock->expects($this->once())->method('charge')->with(99.0). Çağrılmazsa test başarısız olur. Kolay anımsa: stub konuşur, mock dinler. Çoğu durumda stub yeter; yalnızca etkileşimi denetlemek gerektiğinde mock kullan.

Uygulama Stub ile bağımlığı izole et

OrderProcessor, PaymentGateway bağımlığıyla çalışır. StubPaymentGateway adında bir stub yaz (her zaman true döner). OrderProcessorTest sınıfını TestCase'ten türet. testCheckoutCallsGateway metodunda stub ile OrderProcessor oluştur, checkout(99.0) çağır, assertTrue ile true döndüğünü denetle.

Örnek çözümü göster
bool { return true; } } yaz. class OrderProcessorTest extends TestCase içinde testCheckoutCallsGateway: $stub = new StubPaymentGateway(); $processor = new OrderProcessor($stub); $this->assertTrue($processor->checkout(99.0)); ekle.
Örnek çözüm:
<?php
// Bu derste TestCase'i basitçe tanımlıyoruz
class TestCase {
    protected function assertTrue($condition): void {
        if ($condition !== true) { throw new Exception("Koşul true değil"); }
    }
}

interface PaymentGateway {
    public function charge(float $amount): bool;
}

class OrderProcessor {
    private PaymentGateway $gateway;
    public function __construct(PaymentGateway $gateway) { $this->gateway = $gateway; }
    public function checkout(float $amount): bool {
        return $this->gateway->charge($amount);
    }
}

class StubPaymentGateway implements PaymentGateway {
    public function charge(float $amount): bool { return true; }
}

class OrderProcessorTest extends TestCase {
    public function testCheckoutCallsGateway(): void {
        $stub = new StubPaymentGateway();
        $processor = new OrderProcessor($stub);
        $this->assertTrue($processor->checkout(99.0));
    }
}

// Testi çalıştır
$test = new OrderProcessorTest();
$test->testCheckoutCallsGateway();
echo "testCheckoutCallsGateway: BAŞARILI\n";

Kendini test et

  1. getMockBuilder çağrısını tamamla

    <?php
    $gateway = $this->____(PaymentGateway::class)
        ->disableOriginalConstructor()
        ->getMock();
    
    Cevabı göster
    <?php
    $gateway = $this->getMockBuilder(PaymentGateway::class)
        ->disableOriginalConstructor()
        ->getMock();
    
  2. getMockBuilder ne döner?

    • Doğrudan bir mock nesnesi
    • Bir MockBuilder örneği
    • Sınanacak sınıfın kendisi
    • Bir Exception
    Cevabı göster

    Bir MockBuilder örneği — Doğru. getMockBuilder bir MockBuilder döner; getMock() ile mock nesnesi alınır.

  3. Test double türlerini eşleştir

    Stub
    Sabit yanıt döner
    Mock
    Çağrıyı denetler
    Real
    Gerçek servis
    getMock
    Mock üretir

İleri seviye bölümündeki tüm dersler