C# Unit Test Yazımı (xUnit, NUnit, MSTest)
C#’ta unit test yazmayı öğrenin. xUnit, NUnit ve MSTest ile test senaryoları oluşturarak güvenilir yazılım geliştirin.
Yazılım geliştirmede unit test (birim testi), uygulamanın en küçük parçalarını (metot, sınıf veya fonksiyon) izole şekilde test ederek doğru çalıştığından emin olmayı sağlar. C#’ta en yaygın kullanılan test çerçeveleri xUnit, NUnit ve MSTest’tir. Unit testler hataları erken aşamada yakalamayı, kod kalitesini artırmayı ve güvenli refactoring yapmayı mümkün kılar.
Unit Test Nedir?
Unit testler, bir metodun beklenen girdilere karşı doğru çıktıyı üretip üretmediğini kontrol eder. Testler genellikle her senaryo için izole edilir ve dış bağımlılıklardan (veritabanı, dosya sistemi, ağ erişimi) ayrıştırılır.
// Örnek: Test edilecek metot
public class HesapMakinesi
{
public int Topla(int a, int b) => a + b;
}
Yukarıdaki basit örnekte Topla metodu, test edilmesi gereken bir birimdir.
Test Projesi Oluşturma
Visual Studio veya .NET CLI üzerinden test projesi kolayca oluşturulabilir:
// xUnit kullanarak test projesi oluşturma
dotnet new xunit -n HesapMakinesi.Tests
cd HesapMakinesi.Tests
// Test projesine ana projeyi referans ekleyin
dotnet add reference ../HesapMakinesi/HesapMakinesi.csproj
Alternatif olarak nunit veya mstest şablonları da kullanılabilir:
dotnet new nunit -n ProjeAdi.Tests
dotnet new mstest -n ProjeAdi.Tests
xUnit ile Test Yazımı
xUnit, modern ve esnek yapısıyla C# dünyasında en çok tercih edilen test çerçevesidir.
[Fact] özniteliği bağımsız testleri, [Theory] ise parametreli testleri belirtir.
using Xunit;
public class HesapMakinesiTests
{
[Fact]
public void Topla_DogruSonucDondermeli()
{
// Arrange
var h = new HesapMakinesi();
// Act
int sonuc = h.Topla(2, 3);
// Assert
Assert.Equal(5, sonuc);
}
[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, 5, 4)]
[InlineData(10, -2, 8)]
public void Topla_FarkliDegerlerleDogruCalismali(int a, int b, int beklenen)
{
var h = new HesapMakinesi();
Assert.Equal(beklenen, h.Topla(a, b));
}
}
Fact: Tek bir senaryoyu test eder. Theory: Farklı veri setleriyle aynı metodu test eder.
NUnit ile Test Yazımı
NUnit, C# dünyasında uzun süredir kullanılan güçlü bir test framework’tür. Sade yapısı ve zengin assertion çeşitleriyle bilinir.
using NUnit.Framework;
[TestFixture]
public class HesapMakinesiTests
{
private HesapMakinesi hesap;
[SetUp]
public void Setup()
{
hesap = new HesapMakinesi();
}
[Test]
public void Topla_Test()
{
int sonuc = hesap.Topla(4, 6);
Assert.That(sonuc, Is.EqualTo(10));
}
[TestCase(1, 2, 3)]
[TestCase(5, 5, 10)]
public void Topla_FarkliDegerlerle_Test(int a, int b, int beklenen)
{
Assert.That(hesap.Topla(a, b), Is.EqualTo(beklenen));
}
}
NUnit’te [SetUp] metodu her testten önce çalışır, [TestCase] parametreli testler için kullanılır.
MSTest ile Test Yazımı
MSTest, Microsoft’un Visual Studio ile birlikte sunduğu yerleşik test framework’üdür. Özellikle enterprise projelerde tercih edilir.
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class HesapMakinesiTests
{
private HesapMakinesi hesap;
[TestInitialize]
public void Init()
{
hesap = new HesapMakinesi();
}
[TestMethod]
public void Topla_Test()
{
int sonuc = hesap.Topla(2, 8);
Assert.AreEqual(10, sonuc);
}
[DataTestMethod]
[DataRow(1, 1, 2)]
[DataRow(-3, 5, 2)]
public void Topla_FarkliDegerlerle_Test(int a, int b, int beklenen)
{
Assert.AreEqual(beklenen, hesap.Topla(a, b));
}
}
MSTest’te [TestInitialize] her test öncesi hazırlık sağlar, [DataTestMethod] ise veri tabanlı testlerde kullanılır.
Assert (Doğrulama) Metotları
Tüm test kütüphanelerinde benzer doğrulama (assertion) yapıları bulunur:
Assert.Equal(expected, actual)→ Değer eşitliğini test eder.Assert.NotNull(obj)→ Nesnenin null olmadığını doğrular.Assert.True(condition)/Assert.False(condition)Assert.Throws<Exception>(() => ...)→ Beklenen hatayı test eder.
// Örnek: Hata fırlatma testi
[Fact]
public void Bolme_SifiraBolmeHatasiFirlatmali()
{
var h = new HesapMakinesi();
Assert.Throws<DivideByZeroException>(() => h.Bol(5, 0));
}
Testlerin Çalıştırılması
Testleri CLI veya Visual Studio üzerinden çalıştırabilirsiniz:
// .NET CLI ile test çalıştırma
dotnet test
Visual Studio’da “Test Explorer” penceresinden testleri çalıştırabilir, başarılı/başarısız testleri grafik arayüzde görebilirsiniz.
Mocking ve Bağımlılıkların İzolasyonu
Gerçek bağımlılıkları test ortamından ayırmak için mocking kullanılır. Bu sayede testler yalnızca hedef metodu doğrular, dış etkenlerden (veritabanı, servis çağrısı) etkilenmez.
using Moq;
using Xunit;
public interface IEmailServisi
{
void Gonder(string adres, string mesaj);
}
public class KullaniciKaydi
{
private readonly IEmailServisi _mail;
public KullaniciKaydi(IEmailServisi mail) => _mail = mail;
public void Kaydet(string ad)
{
_mail.Gonder("admin@site.com", $"{ad} kayıt edildi.");
}
}
public class KullaniciKaydiTests
{
[Fact]
public void Kaydet_MailGondermeli()
{
var mock = new Mock<IEmailServisi>();
var kayit = new KullaniciKaydi(mock.Object);
kayit.Kaydet("Ahmet");
mock.Verify(m => m.Gonder("admin@site.com", "Ahmet kayıt edildi."), Times.Once);
}
}
Moq kütüphanesi, sahte (mock) nesneler oluşturarak test ortamını izole eder.
Test Organizasyonu ve İsimlendirme
- Test isimleri açıklayıcı olmalıdır:
MetotAdı_Durum_BeklenenSonuçbiçiminde. - Testler tek bir davranışı test etmelidir.
- Arrange–Act–Assert (Hazırlık–İşlem–Doğrulama) düzenini takip edin.
- Test bağımlılıklarını minimumda tutun.
- Testler birbirinden bağımsız çalışmalıdır.
Gerçek Hayat Örneği: Sipariş Hesaplama Testi
Aşağıdaki örnek, bir sipariş toplamı hesaplama işlemini test eder.
// Uygulama kodu
public class Siparis
{
public List<decimal> UrunFiyatlari { get; set; } = new();
public decimal Toplam() => UrunFiyatlari.Sum();
}
// Test
public class SiparisTests
{
[Fact]
public void Toplam_DogruSonucDondermeli()
{
var s = new Siparis();
s.UrunFiyatlari.AddRange(new[] { 10m, 20m, 30m });
Assert.Equal(60m, s.Toplam());
}
}
Bu örnek, iş mantığının doğru çalıştığını garanti altına almak için temel bir birim testtir.
Performans ve En İyi Uygulamalar
- Her test izole olmalı, global duruma bağlı olmamalıdır.
- Testleri küçük tutun – bir test yalnızca bir davranışı kontrol etmelidir.
- Mock veya stub kullanarak dış bağımlılıkları izole edin.
- Testleri sürekli entegrasyon (CI) pipeline’ına entegre edin.
- Yavaş çalışan testleri profilleyin ve optimize edin.
TL;DR
- Unit Test: Kodun küçük birimlerini izole biçimde test eder.
- xUnit: Modern, sade ve .NET topluluğunda en popüler test çerçevesidir.
- NUnit: Güçlü assertion’lar ve attribute tabanlı test yaklaşımıyla klasik framework.
- MSTest: Visual Studio ile tam entegre Microsoft çözümü.
- Mocking: Dış bağımlılıkları sahte nesnelerle izole eder.
- AAA Modeli: Arrange–Act–Assert test düzenini izleyin.
- dotnet test komutu tüm testleri CLI üzerinden çalıştırır.
İlişkili Makaleler
C# Dependency Injection Temelleri
C#’ta Dependency Injection kavramını öğrenin. Bağımlılıkların yönetimi, gevşek bağlılık ve test edilebilirlik örneklerle anlatılıyor.
C# için Visual Studio / VS Code İpuçları
C# geliştiricileri için Visual Studio ve VS Code ipuçlarını öğrenin. Verimlilik artıran kısayollar ve geliştirme teknikleri.