Bölüm 6 / 12
Entegrasyon testi
WebApplicationFactory, test veritabanı.
13 dakikalık okuma
Birim testler parçaların doğruluğunu kanıtladı; ama üretimde seni
yakan hataların önemli bölümü parçalarda değil bağlantılarda yaşar: DI kaydı unutulmuş
servis, sırası yanlış middleware, gerçek motorda başka davranan sorgu, yanlış bağlanan
yapılandırma. Bu ders ASP.NET Core'un entegrasyon testi altyapısını kurar:
WebApplicationFactory ile uygulamanın tamamını bellek içinde ayağa
kaldırmak, ConfigureTestServices ile sınır servislerini değiştirmek
(12. hattaki Nest overrideProvider'ın .NET karşılığı), test veritabanı
seçenekleri — ve EF Core InMemory sağlayıcısının neden sahte güven ürettiği —
Testcontainers ile gerçek motor, test izolasyonu stratejileri. Kapanışta 13. hattın senedi
ödenir: kimlik doğrulamalı entegrasyon testi ve her korumalı ucun 401/403/IDOR
negatif testleri.
01Ne öğreneceksin
- Entegrasyon testinin hangi hata sınıfını yakaladığı
WebApplicationFactory: tam uygulamayı bellek içi sunucuda koşturmak;ProgramerişimiConfigureTestServicesile servis değiştirme veUseEnvironment/test yapılandırması- Test veritabanı kararı: EF InMemory ↔ SQLite ↔ gerçek motor ↔ Testcontainers ve InMemory'nin tuzakları
- Test izolasyonu: Respawn ile temizleme, işlem geri alma, koleksiyonlarla paralellik yönetimi
- Kimlik doğrulamalı test: sahte kimlik doğrulama şeması yazmak
- Negatif güvenlik testleri: 401 ↔ 403 ↔ IDOR (13-03 senedinin kapanışı)
- Dış HTTP sınırlarının testte nasıl ele alınacağı
02Bağlantıların hata sınıfı
Şu hataların hiçbirini birim test göremez — hepsi gerçek üretim vakası desenidir:
- Servis DI konteynerine kaydedilmemiş; uygulama ilk istekte patlıyor (Hat 5). Ya da yanlış ömürle kaydedilmiş: singleton'a hapsolan scoped DbContext.
- Middleware sırası ters: yetkilendirme, CORS'tan önce koşuyor; hata sayfası üretimde ayrıntı sızdırıyor (13-09).
- Model binding beklediğin alanı doldurmuyor; doğrulama niteliği hiç tetiklenmiyor.
- LINQ sorgusu bellek içinde doğru, gerçek motorda farklı çeviriliyor ya da çevrilemiyor; büyük/küçük harf ve null karşılaştırmaları motora göre değişiyor (Hat 7).
appsettings'teki anahtar adı kodla uyuşmuyor; değer null geliyor.
Ortak nokta: hata tek bir sınıfın içinde değil, parçaların sözleşmesinde. Entegrasyon testinin işi bu sözleşmeyi gerçek parçalarla doğrulamaktır: gerçek DI konteyneri, gerçek middleware boru hattı, gerçek yönlendirme, mümkün olduğunca gerçek veritabanı. 2. dersteki kupa görüşünün haklılık payı da buradadır: bu katman, ince API'lerde güvenin ana kaynağıdır.
03WebApplicationFactory: uygulama bellek içinde
Microsoft.AspNetCore.Mvc.Testing paketinin verdiği
WebApplicationFactory<TEntryPoint>, uygulamanı gerçek
Program.cs'inden — tüm DI kayıtları, middleware'ler, yönlendirmeyle —
bellek içi bir sunucuda (TestServer) ayağa kaldırır; ağ soketi açılmaz, istekler doğrudan
boru hattına verilir:
public class BasvuruApiTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient istemci;
public BasvuruApiTests(WebApplicationFactory<Program> fabrika)
=> istemci = fabrika.CreateClient(); // uygulama bir kez ayağa kalkar (3. ders)
[Fact]
public async Task Ilanlar_Listeleme_BasariylaDoner()
{
var cevap = await istemci.GetAsync("/api/ilanlar");
cevap.EnsureSuccessStatusCode();
Assert.Equal("application/json", cevap.Content.Headers.ContentType?.MediaType);
}
}
İki kurulum ayrıntısı bilinmezse ilk denemede duvara toslatır: (1) minimal API'lerde
Program sınıfı derleyici üretimidir ve dışarıdan görünmez; test projesinin onu
görebilmesi için Program.cs'in sonuna public partial class Program { }
satırı eklenir (ya da InternalsVisibleTo kullanılır). (2) Fabrika pahalıdır —
3. dersin fixture bilgisi burada zorunluluktur: IClassFixture ile sınıf başına
bir kez kurulur.
12. hattın senedini burada ödeyelim: Node tarafında bu testin ön şartı, uygulamayı
dinlemeye başlamadan tarif eden app'in server'dan ayrılmasıydı
(12-08) — Express'te bunu el ile kurmuştun. ASP.NET Core'da aynı ayrım çerçevenin içinde
hazırdır: Program.cs uygulamayı tarif eder, kimin dinleyeceğine ortam
karar verir — üretimde Kestrel, testte TestServer. Nest'teki
Test.createTestingModule + overrideProvider ikilisinin (12-09)
karşılığı ise bir sonraki bölümdür.
04ConfigureTestServices: sınırı değiştir, kalanı gerçek bırak
Uygulamanın tamamını gerçek çalıştırmak istiyoruz ama bazı sınırlar testte gerçek
olamaz: e-posta sağlayıcısına gerçekten posta atılmaz, dış kimlik API'sine gerçekten
gidilmez. WithWebHostBuilder + ConfigureTestServices, fabrikayı
klonlayıp DI kayıtlarını değiştirir:
var fabrika = temelFabrika.WithWebHostBuilder(b =>
{
b.UseEnvironment("Testing"); // appsettings.Testing.json devreye girer
b.ConfigureTestServices(s =>
{
s.RemoveAll<IPostaServisi>(); // gerçek kaydı sök
s.AddSingleton<IPostaServisi, SahtePostaServisi>(); // yerine spy/fake (4. ders)
});
});
Kritik ayrıntı isimdedir: ConfigureServices değil
ConfigureTestServices — bu blok, uygulamanın kendi kayıtlarından
sonra çalışır; "son kayıt kazanır" kuralıyla (Hat 5) değiştirme garantidir. Nest'te
overrideProvider(PostaServisi).useValue(sahte) ile yaptığının birebir
karşılığıdır — senet ödendi. Aynı yerden test yapılandırması da yönetilir:
UseEnvironment("Testing") + appsettings.Testing.json ya da
ConfigureAppConfiguration ile bellek içi anahtarlar. Ölçü, 4. dersin kuralının
sistem hâlidir: yalnız süreç dışına çıkan sınırları değiştir; iş mantığını, middleware'i,
doğrulamayı gerçek bırak — ne kadar çok şeyi değiştirirsen, test o kadar az şeyi
kanıtlar.
05Test veritabanı kararı
Entegrasyon testinin en çok tartışılan sorusu: veritabanı ne olacak? Seçenekler ve dürüst bedelleri:
| Seçenek | Ne verir | Bedeli |
|---|---|---|
| EF Core InMemory | Sıfır kurulum, çok hızlı | İlişkisel değildir — aşağıdaki tuzak listesi; EF ekibi test için önermiyor |
| SQLite (bellek içi) | Gerçek ilişkisel davranış, hızlı, kurulumsuz | Üretim motorun değil: tip sistemi gevşek, bazı fonksiyonlar ve davranışlar farklı; bağlantı kapanınca veritabanı yok olur — bağlantı test boyunca açık tutulmalı |
| Gerçek motor (yerel kurulum) | Üretimle birebir davranış | Herkesin makinesinde ve CI'da aynı sürümün kurulu olması gerekir; ortam sürüklenmesi |
| Testcontainers | Docker'da gerçek motor, testin kendisi tarafından kurulup yıkılır; sürüm sabit, CI'da aynı | Docker gereksinimi; ilk imaj indirme; saniyeler mertebesinde açılış (koleksiyon fixture'ıyla bir kez ödenir) |
InMemory'nin tuzakları — "testte yeşil, üretimde kırık"ın başlıca üreticisi: yabancı anahtar ve benzersizlik kısıtlarını uygulamaz (ihlal eden kayıt sessizce yazılır, üretimde patlar); işlemler (transaction) fiilen yok sayılır — geri alma senaryon test edilemez; ham SQL çalıştıramaz; sorgu davranışı LINQ-to-Objects'tir — büyük/küçük harf duyarlılığı, null semantiği, tarih işlemleri gerçek motordan farklıdır (Hat 7'deki motor farkları burada geri döner). Sonuç net: sorgu, kısıt ya da işlem davranışı doğrulanacaksa InMemory kullanma.
Modern varsayılan, Testcontainers ile üretim motorunun ta kendisidir:
public class VeritabaniFixture : IAsyncLifetime
{
public PostgreSqlContainer Konteyner { get; } = new PostgreSqlBuilder()
.WithImage("postgres:16") // üretimdeki sürümün aynısı
.Build();
public Task InitializeAsync() => Konteyner.StartAsync();
public Task DisposeAsync() => Konteyner.DisposeAsync().AsTask();
}
Fabrikanın ConfigureTestServices'inde DbContextOptions kaydı
söküp bağlantıyı Konteyner.GetConnectionString()'e yönlendirirsin; şema,
testin başında migration'larla kurulur — böylece migration'ların da her koşuda test edilmiş
olur. Karar cümlesi: sorgular üretim motoruna karşı, saf servis mantığı birim testte
— SQLite, Docker'ın bulunmadığı ortamlar için makul orta yoldur, yeter ki farkları bilerek
seçilsin. (Konteyner kavramı 17. hatta derinleşecek; burada kullanıcısısın, kurucusu
değil.)
06İzolasyon: her test temiz sayfa
Gerçek veritabanı paylaşıldığı anda 2. dersin kararsızlık uyarısı geri gelir: bir testin yazdığı kayıt diğerinin sorgusunu şişirir, koşu sırası sonucu değiştirir. Stratejiler:
- Testten sonra temizle — Respawn: yaygın pratik. Respawn kütüphanesi, yabancı
anahtar grafiğini çözümleyip tabloları doğru sırada boşaltır; her testin başında
ResetAsyncçağrılır. Şemayı yeniden kurmaktan çok daha hızlıdır. - İşleme sar, geri al: test bir transaction içinde koşar, sonunda rollback. Çok hızlıdır; ama test edilen kodun kendi işlem yönetimi varsa iç içe geçer ve commit davranışını test edemezsin.
- Test başına ayrı veritabanı/şema: en güçlü izolasyon, en yüksek maliyet; genelde koleksiyon başına bir veritabanı yeterli dengedir.
Hangisi seçilirse seçilsin iki kural değişmez. Birincisi 3. dersten: aynı veritabanını paylaşan test sınıfları aynı koleksiyona konur — paralel koşu, izolasyon stratejini ezmesin. İkincisi: her test kendi verisini kurar (Arrange'de API üzerinden ya da doğrudan context ile) ve asla "2 numaralı testin yazdığı kayda" yaslanmaz; ortak tohum verisi yalnızca değişmeyen sözlük verisi (iller, kadro türleri) için meşrudur. Node tarafında Jest'in modül önbelleğiyle yaşadığın izolasyon meselesinin (12-03) genel dersi burada da geçerlidir: izolasyonu bozan şey her zaman paylaşılan durumdur; aracı değil, paylaşımı yönet.
07Kimlik doğrulamalı test
Korumalı uçları test etmenin yanlış yolu, testte kimlik doğrulamayı kapatmaktır —
o zaman 13. hattın tüm kuralları test edilemez hâle gelir. Doğru yol, boru hattına testin
denetlediği bir sahte kimlik doğrulama şeması takmaktır (13-08'deki şema mimarisinin
testteki meyvesi): gerçek middleware'ler, gerçek [Authorize] nitelikleri,
gerçek politikalar çalışır; yalnız kimliğin kaynağı sahtedir.
public class TestKimlikHandler(IOptionsMonitor<AuthenticationSchemeOptions> opts,
ILoggerFactory logger, UrlEncoder encoder)
: AuthenticationHandler<AuthenticationSchemeOptions>(opts, logger, encoder)
{
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue("X-Test-Kullanici", out var kullanici))
return Task.FromResult(AuthenticateResult.NoResult()); // kimliksiz istek → 401 yolu
var iddialar = new[]
{
new Claim(ClaimTypes.NameIdentifier, kullanici!),
new Claim(ClaimTypes.Role, Request.Headers["X-Test-Rol"].FirstOrDefault() ?? "aday"),
};
var kimlik = new ClaimsIdentity(iddialar, Scheme.Name);
var bilet = new AuthenticationTicket(new ClaimsPrincipal(kimlik), Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(bilet));
}
}
// fabrikada:
b.ConfigureTestServices(s =>
{
s.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, TestKimlikHandler>("Test", null);
s.PostConfigure<AuthenticationOptions>(o =>
{
o.DefaultAuthenticateScheme = "Test"; // varsayılan şemayı teste çevir
o.DefaultChallengeScheme = "Test";
});
});
Artık her test, başlıkla istediği kimliğe bürünür: X-Test-Kullanici: 42 +
X-Test-Rol: denetci. Böylece rol ve politika senaryoları — "denetçi görür,
aday göremez" — sıradan birer teoriye dönüşür. Gerçek JWT üretip doğrulamayı da gerçek
çalıştırmak mümkündür (testte imzalama anahtarı üretilir); jetonun kendisinin doğrulanması
test ediliyorsa değerlidir, aksi hâlde sahte şema daha hızlı ve yeterlidir.
08401, 403 ve IDOR: negatif güvenlik testleri
2. dersin negatif disiplinini şimdi somut koda bağlıyoruz — 13-03'te açılan senet burada kapanır. Korumalı her uç için asgari üçlü:
[Fact]
public async Task Basvuru_KimliksizIstekte_401Doner()
{
var cevap = await istemci.GetAsync("/api/basvurular/7"); // X-Test-Kullanici yok
Assert.Equal(HttpStatusCode.Unauthorized, cevap.StatusCode);
}
[Fact]
public async Task BasvuruSilme_AdayRolunde_403Doner() // uç, denetçi ister
{
istemci.DefaultRequestHeaders.Add("X-Test-Kullanici", "42");
istemci.DefaultRequestHeaders.Add("X-Test-Rol", "aday");
var cevap = await istemci.DeleteAsync("/api/basvurular/7");
Assert.Equal(HttpStatusCode.Forbidden, cevap.StatusCode);
}
[Fact]
public async Task Basvuru_BaskaKullanicininKaydina_404Doner() // IDOR: 13-03
{
await KullaniciOlarakBasvuruOlustur(kullaniciId: "42", basvuruId: 7);
istemci.DefaultRequestHeaders.Add("X-Test-Kullanici", "99"); // farklı kullanıcı
var cevap = await istemci.GetAsync("/api/basvurular/7");
Assert.Equal(HttpStatusCode.NotFound, cevap.StatusCode); // varlığı bile sızdırma
}
Üçünün ayrımını 13. hattan hatırla: 401 "kimsin bilmiyorum" (kimlik yok/geçersiz), 403 "kimsin biliyorum, yetkin yok" (rol/politika), IDOR ise yetkili görünen kullanıcının başkasının kaynağına nesne kimliğiyle uzanmasıdır — dünyanın en yaygın API açığı ve 14-14'te gördüğün gibi rol hesapları verilmeden sızma testinde bile yakalanamayan sınıf. Cevapta 403 yerine 404 dönmek bilinçli karardır: kaynağın varlığını dahi sızdırmamak. Liste uçları da unutulmaz: "99 numaralı kullanıcının listesinde 42'nin başvurusu görünmemeli" — filtre sızması testi.
Kural olarak kalıplaştır: her korumalı uca en az bir 401, bir 403/404 ve — nesne
sahipliği varsa — bir IDOR testi. Bu testler bir kez yazıldığında, 13. hattın tüm
tasarım kararları regresyon korumasına kavuşur: yarın biri [Authorize]'ı yanlışlıkla
silerse ya da sorgudan sahiplik filtresini düşürürse, üretimden önce burada kırmızı yanar.
Sızma testi raporundan (14-14) gelen her bulgunun kapanışına da böyle bir regresyon testi
eklenir — bulgu bir daha sessizce açılamaz (5. dersin hata akışıyla aynı ilke).
Son sınır — dış HTTP servisleri: entegrasyon testinde de gerçek üçüncü partiye gidilmez (yavaş, kararsız, bazen ücretli). Ya 4. dersteki sahte handler fabrika üzerinden takılır ya da WireMock.Net gibi bir araçla testin kurduğu yerel sahte sunucu kullanılır — istek gerçekten HTTP hattından çıkar, cevabı senaryo belirler. Kendi sisteminin sınırı, entegrasyon testinin de sınırıdır.
09Mini alıştırma — uçtan kanıt
Yaklaşık 20 dakika · dotnet CLI (Hat 5-6'daki API'n; yoksa dotnet new webapi)
- Altyapı. Test projesine
Microsoft.AspNetCore.Mvc.Testingekle;Program.cs'epublic partial class Program { }satırını koy;IClassFixture<WebApplicationFactory<Program>>ile ilk düz testi yaz: ana uç 200 dönüyor mu? - Sınırı değiştir. Bir sınır servisini (posta, dış doğrulama)
ConfigureTestServices+RemoveAllile elle yazdığın spy fake'e çevir; bir POST isteğinden sonra fake'in kaydından komutun gittiğini doğrula. - InMemory tuzağını kanıtla. Context'i EF InMemory'ye bağla ve benzersizlik kısıtını ihlal eden iki kaydı arka arkaya yaz: test yeşil kalacak. Aynı senaryoyu SQLite bellek içi (ya da kuruluysa Testcontainers) ile tekrarla: ikinci kayıt patlayacak. "Testte yeşil, üretimde kırık" cümlesini kendi gözünle görmüş ol.
- Sahte kimlik. Bölüm 07'deki
TestKimlikHandler'ı kur; korumalı bir uca kimlikli istekle 200 aldığını doğrula. - Negatif üçlü. Aynı uç için 401 (başlıksız), 403 (yanlış rol) ve IDOR
(başka kullanıcının kaydına 404) testlerini yaz. Sonra
[Authorize]'ı geçici olarak kaldırıp hangi testlerin kırmızıya döndüğünü izle — güvenlik regresyon ağının çalıştığının kanıtı budur. Niteliği geri koy.
10Kendini sına
Entegrasyon testi birim testin göremediği hangi hata sınıfını yakalar? WebApplicationFactory ne yapar ve hangi iki kurulum ayrıntısı bilinmelidir?
Birim test parçanın iç mantığını doğrular; parçaların
sözleşmesinde yaşayan hatalara kördür: DI konteynerine kaydedilmemiş ya da yanlış
ömürle kaydedilmiş servis, middleware sıra hatası, model binding/doğrulama uyumsuzluğu,
bellek içinde doğru görünüp gerçek motorda farklı çevrilen LINQ sorgusu, yapılandırma
anahtarının kodla uyuşmaması. Entegrasyon testi bu sözleşmeyi gerçek parçalarla doğrular.
WebApplicationFactory<Program>, uygulamayı gerçek Program.cs'inden —
tüm kayıt ve boru hattıyla — bellek içi TestServer'da ayağa kaldırır; ağ soketi açılmaz,
CreateClient()'ın verdiği HttpClient istekleri doğrudan boru hattına iletir,
böylece test gerçekçi ama hızlı ve kararlıdır. İki kurulum ayrıntısı: minimal API'de
Program derleyici üretimi olduğundan test projesinin görmesi için
public partial class Program { } eklenir; ve fabrika pahalı olduğundan
IClassFixture ile paylaşılır — her testte uygulamayı yeniden ayağa kaldırmak
koşuyu gereksizce şişirir. Kavramsal temel de anılmaya değer: uygulamayı tarif etmek ile
dinletmek ayrıdır (Node'da elle kurduğun app/server ayrımı); ASP.NET Core'da bu ayrım
çerçevede hazır olduğu için TestServer takılabilir.
ConfigureTestServices nasıl çalışır, neden sıradan ConfigureServices değil? Neyi değiştirmeli, neyi gerçek bırakmalısın?
WithWebHostBuilder fabrikayı klonlar;
ConfigureTestServices bloğu, uygulamanın kendi servis kayıtlarından
sonra çalışır ve DI'daki "son kayıt kazanır" kuralı sayesinde değiştirme garantiye
alınır — sıradan ConfigureServices ile araya girmeye çalışmak, uygulama
kaydının senin kaydını ezmesiyle sonuçlanabilir. Tipik desen:
RemoveAll<IPostaServisi>() + sahtesini ekle; yapılandırma için
UseEnvironment("Testing") ile appsettings.Testing.json devreye
alınır. Bu, NestJS'te Test.createTestingModule +
overrideProvider().useValue() ile yapılan işin .NET karşılığıdır — kavram
çerçeveden bağımsız: konteynerdeki kaydı test çifte değiştirir, uygulama kodu değişmez.
Ölçü: yalnız süreç dışına çıkan sınırlar (e-posta, dış HTTP, kuyruk) değiştirilir; iş
mantığı, doğrulama, middleware, yetkilendirme ve mümkünse veritabanı gerçek bırakılır.
Gerekçe testin anlamıdır: her değiştirilen parça, testin kanıtlamadığı bir bölgedir —
her şeyi sahteye çeviren "entegrasyon" testi, pahalı bir birim testinden ibarettir.
Test veritabanı seçenekleri nelerdir? EF Core InMemory sağlayıcısının tuzaklarını say ve modern varsayılan kararı gerekçelendir.
Dört seçenek: EF InMemory — kurulumsuz ve hızlı ama ilişkisel değil; SQLite bellek içi — gerçek ilişkisel davranış, ama üretim motoru değil ve bağlantı kapanınca veritabanı yok olduğundan bağlantı test boyunca açık tutulmalı; yerel gerçek motor — birebir davranış ama herkesin makinesinde ve CI'da aynı sürümü gerektirir; Testcontainers — testin kendisinin Docker'da kurup yıktığı gerçek motor, sürümü imajla sabitlenir, CI'da aynen koşar; bedeli Docker gereksinimi ve koleksiyon fixture'ıyla bir kez ödenen açılış süresi. InMemory'nin tuzakları: yabancı anahtar ve benzersizlik kısıtlarını uygulamaz (ihlalli kayıt sessizce yazılır — testte yeşil, üretimde patlama), işlemleri fiilen yok sayar (geri alma davranışı test edilemez), ham SQL çalıştıramaz ve sorguları LINQ-to-Objects olarak koşturur — harf duyarlılığı, null semantiği, tarih davranışı gerçek motordan farklıdır; EF ekibi de test için önermez. Karar: sorgu, kısıt ya da işlem davranışı doğrulanıyorsa üretimdeki motorun kendisi (Testcontainers) kullanılır — migration'lar da böylece her koşuda doğrulanır; saf servis mantığı zaten birim testin işidir; SQLite, Docker'sız ortamlar için farkları bilinerek seçilen orta yoldur.
Entegrasyon testlerinde izolasyon nasıl sağlanır? Kimlik doğrulamalı uçlar nasıl test edilir ve her korumalı uç için asgari negatif test kümesi nedir?
İzolasyon stratejileri: her testin başında Respawn ile tabloları
yabancı anahtar sırasına göre boşaltmak (hızlı ve genel çözüm), testi transaction'a sarıp
geri almak (çok hızlı ama kodun kendi işlem/commit davranışını test edemez) ya da
koleksiyon başına ayrı veritabanı. İki değişmez kural: aynı veritabanını paylaşan test
sınıfları aynı xUnit koleksiyonuna konur ki paralellik izolasyonu ezmesin; ve her test
kendi verisini kurar — başka testin yazdığına yaslanan test, sıra değişince kırılır.
Kimlik doğrulama testte kapatılmaz — kapatılırsa 13. hattın kuralları test dışı
kalır; bunun yerine AuthenticationHandler'dan türeyen sahte bir şema takılır:
istek başlığından kullanıcı/rol okuyup ClaimsPrincipal üreten handler,
DefaultAuthenticateScheme teste çevrilerek kaydedilir; gerçek
[Authorize] ve politikalar aynen çalışır, yalnız kimliğin kaynağı sahtedir.
Asgari negatif küme: kimliksiz istek → 401; kimlikli ama yetkisiz rol → 403;
nesne sahipliği olan uçlarda başka kullanıcının kaydına erişim → 404/403 (IDOR),
404 tercihi varlığı bile sızdırmamak içindir; liste uçlarında filtre sızması testi. Bu
testler, yanlışlıkla silinen bir [Authorize] ya da düşürülen sahiplik filtresini üretimden
önce kırmızıya çevirir — güvenlik kararlarının regresyon ağıdır.
11Sınav köşesi
Yazılıda nasıl sorulur
(1) Entegrasyon testi nedir, birim testten farkı nedir? (2) Entegrasyon testi hangi hata türlerini yakalar? (3) ASP.NET Core'da entegrasyon testi hangi araçla yazılır? (4) Test ortamında servisler nasıl değiştirilir? (5) Test veritabanı seçenekleri nelerdir, artıları ve eksileri nedir? (6) Bellek içi veritabanı sağlayıcısı kullanmanın sakıncaları nelerdir? (7) Testler arasında veri izolasyonu nasıl sağlanır? (8) Kimlik doğrulama gerektiren uçlar nasıl test edilir? (9) 401 ile 403 durum kodları arasındaki fark nedir? (10) IDOR açığı testlerle nasıl önlenir?
Sözlüde nasıl anlatılır — 2 dakikalık taslak
Düzen: (1) Kapsam — "Entegrasyon testiyle parçaların sözleşmesini doğrularım: DI kayıtları, middleware sırası, model binding, gerçek motorda sorgu davranışı — birim testin kör olduğu katman." (2) Araç — "WebApplicationFactory uygulamayı gerçek Program'dan bellek içi sunucuda kaldırır; ConfigureTestServices ile yalnız süreç dışı sınırları (posta, dış API) sahteye çeviririm — ne kadar çok şeyi değiştirirsem test o kadar az şey kanıtlar." (3) Veritabanı — "EF InMemory kullanmam: kısıtları ve işlemleri uygulamaz, sorgusu LINQ-to-Objects'tir — sahte güven verir. Testcontainers ile üretim motorunun aynısını Docker'da kaldırırım; izolasyonu Respawn ile, paralelliği aynı veritabanını paylaşanları aynı koleksiyona koyarak yönetirim; her test kendi verisini kurar." (4) Güvenlik — "Kimlik doğrulamayı testte kapatmam; sahte bir kimlik şeması takarım — gerçek [Authorize] ve politikalar çalışır. Her korumalı uca asgari üçlüyü yazarım: 401, 403 ve IDOR — başkasının kaydına 404." (5) Kıdem vuruşu — "Bu negatif testler güvenlik kararlarımın regresyon ağıdır: yarın biri [Authorize]'ı silerse ya da sahiplik filtresini düşürürse üretimden önce burada kırmızı yanar; sızma testi bulgularını da kapanışta birer entegrasyon testine çevirir, bir daha sessizce açılmalarını engellerim."
