Dış API’lerle entegrasyonları test etmek, bir web uygulamasının en kırılgan kısımlarından biridir. Teorik olarak, testler yazarız, HTTP istemcilerini mock’larız ve kendimizi güvende hissederiz. Pratikte ise, API’ler değişir, alanlar kaybolur, durum kodları değişir ve üretim yine de bozulur.
<p>Bunu zor yoldan öğrendim.</p>
<p>Bir projede, tüm testlerim başarılıydı. Mock'larım tam olarak beklediğim gibi geri döndü. Bir hafta sonra, dış API, yanıtın bir alanını kaldırdı. Mock'larım bu değişikliği bilmiyordu. Üretim ise biliyordu.</p>
<p>Mock'lar her şeyin yolunda olduğunu söyledi. Gerçekler ise karşıtını gösterdi.</p>
<p>İşte bu tür bir sorun <strong>contract testing</strong>'in çözmeyi amaçladığı tam yer. Bu makalede, gerçek dünyadaki bir *<em>Laravel</em>* örneği ile PHP'de dış API'ler için contract testing nasıl kullanılır, göstereceğim.</p>
<h2>
<a name="why-mocking-external-apis-is-not-enough" href="#why-mocking-external-apis-is-not-enough">
</a>
Neden Dış API'leri Mocklamak Yeterli Değil
</h2>
<p>Dış API'leri mocklamak faydalıdır. Hâlâ yapıyorum. Testleri hızlı, belirleyici ve ucuz hale getirir. Ancak mock'ların bir ölümcül hatası vardır:</p>
<blockquote>
<p>API hakkında varsayımlarınızı test ederler, API'yi değil.</p>
</blockquote>
<p>Üretimde gördüğüm tipik problemler:</p>
<ul>
<li>API bir alanı kaldırır veya adını değiştirir.</li>
<li>İç içe olan yapının şekli değişir.</li>
<li>API bazı uç durumlarda 200 yerine 404 döndürmeye başlar.</li>
<li>API, istek gövdesine bir zorunlu alan ekler.</li>
</ul>
<p>Mock'larınızı manuel olarak güncellemedikçe bunları asla yakalayamazsınız. Bu, mock'ların sessizce gerçeklikten uzaklaşabileceği anlamına gelir.</p>
<h2>
<a name="what-is-contract-testing-in-plain-english" href="#what-is-contract-testing-in-plain-english">
</a>
Contract Testing Nedir (Açık Bir Dille)
</h2>
<p>Contract testing, mocking ve tam entegrasyon testleri arasında yer alır.</p>
<p>Şunu söylemek yerine:</p>
<blockquote>
<p>“API'nin döndüğünü düşündüğüm şey bu,”</p>
</blockquote>
<p;>şunu söylersiniz:</p>
<blockquote>
<p>“Uygulamam (tüketici) ile API (sağlayıcı) arasındaki sözleşme budur.”</p>
</blockquote>
<p>Tüketici odaklı contract testing ile:</p>
<p>Sağlayıcı, sözleşmeyi bozan bir değişiklik yaparsa, testler <strong>üretim bozulmadan önce</strong> başarısız olur.</p>
<p>Bu, bozulma yapan API değişikliklerini bir çalışma zamanı sürprizinden, bir inşa (build) zamanı hatasına dönüştürür.</p>
<h2>
<a name="realworld-scenario-laravel-as-api-consumer" href="#realworld-scenario-laravel-as-api-consumer">
</a>
Gerçek Dünya Senaryosu: Laravel'in API Tüketicisi Olarak Kullanımı
</h2>
<p>Bir Laravel uygulamasının harici bir faturalama API'si ile entegre olduğunu varsayalım:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>GET /api/customers/{id}Response:
{
“id”: 123,
“email”: “[email protected]”,
“is_active”: true
}
<p>Laravel servisin:</p>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>class BillingClient{
public function getCustomer(int $id): array
{
$response = Http::get(“https://billing.example.com/api/customers/{$id}”);
return $response->json();
}}


