Unit Testing¶
Unit testler, kodun en küçük birimlerini izole ederek doğrular; yanlış yazılan testler güvenilmez sonuçlara ve bakım yüküne yol açar.
1. Test İsimlendirmesini Anlamsız Bırakmak¶
❌ Yanlış Kullanım: Ne test edildiği anlaşılmayan isimler kullanmak.
[Fact]
public void Test1()
{
var service = new OrderService();
var result = service.Calculate(100, 0.1m);
Assert.Equal(90, result);
}
✅ İdeal Kullanım: MethodName_Scenario_ExpectedResult formatını kullanın.
[Fact]
public void Calculate_WithTenPercentDiscount_ReturnsDiscountedPrice()
{
var service = new OrderService();
var result = service.Calculate(100, 0.1m);
Assert.Equal(90, result);
}
2. Arrange-Act-Assert Yapısını Kullanmamak¶
❌ Yanlış Kullanım: Test adımlarını karıştırmak.
[Fact]
public void CreateOrder_Test()
{
var order = new Order();
order.AddItem(new Product("Laptop", 5000));
Assert.Equal(1, order.Items.Count);
order.AddItem(new Product("Mouse", 200));
Assert.Equal(2, order.Items.Count);
Assert.Equal(5200, order.TotalPrice);
}
✅ İdeal Kullanım: Arrange, Act, Assert bölümlerini net ayırın.
[Fact]
public void AddItem_WhenTwoItemsAdded_CalculatesTotalCorrectly()
{
// Arrange
var order = new Order();
var laptop = new Product("Laptop", 5000);
var mouse = new Product("Mouse", 200);
// Act
order.AddItem(laptop);
order.AddItem(mouse);
// Assert
Assert.Equal(2, order.Items.Count);
Assert.Equal(5200, order.TotalPrice);
}
3. Birden Fazla Şeyi Test Etmek¶
❌ Yanlış Kullanım: Tek testte birden fazla davranışı doğrulamak.
[Fact]
public void UserService_Tests()
{
var service = new UserService(_mockRepo.Object);
// Kullanıcı oluşturma testi
var user = service.Create("Ali", "ali@test.com");
Assert.NotNull(user);
// Kullanıcı güncelleme testi
user.Name = "Veli";
service.Update(user);
Assert.Equal("Veli", user.Name);
// Kullanıcı silme testi
service.Delete(user.Id);
Assert.Null(service.GetById(user.Id));
}
✅ İdeal Kullanım: Her test tek bir davranışı doğrulasın.
[Fact]
public void Create_WithValidData_ReturnsUser()
{
var service = new UserService(_mockRepo.Object);
var user = service.Create("Ali", "ali@test.com");
Assert.NotNull(user);
Assert.Equal("Ali", user.Name);
}
[Fact]
public void Delete_WithExistingUser_RemovesFromRepository()
{
var service = new UserService(_mockRepo.Object);
service.Delete(1);
_mockRepo.Verify(r => r.Delete(1), Times.Once);
}
4. Test Verisi Oluşturmayı Karmaşıklaştırmak¶
❌ Yanlış Kullanım: Her testte uzun nesne oluşturma kodu tekrarlamak.
[Fact]
public void CalculateShipping_ForPremiumCustomer_ReturnsFreeShipping()
{
var customer = new Customer
{
Id = 1, Name = "Ali", Email = "ali@test.com",
Type = CustomerType.Premium, CreatedAt = DateTime.UtcNow,
Address = new Address { City = "Istanbul", Country = "TR", ZipCode = "34000" }
};
var order = new Order
{
Id = 1, CustomerId = 1, TotalPrice = 500,
Items = new List<OrderItem> { new() { ProductId = 1, Quantity = 2, Price = 250 } }
};
// ... test mantığı
}
✅ İdeal Kullanım: Test Data Builder ile temiz test verisi oluşturun.
public class CustomerBuilder
{
private CustomerType _type = CustomerType.Standard;
public CustomerBuilder AsPremium() { _type = CustomerType.Premium; return this; }
public Customer Build() => new()
{
Id = 1, Name = "Test User", Email = "test@test.com",
Type = _type, CreatedAt = DateTime.UtcNow,
Address = new Address { City = "Istanbul", Country = "TR", ZipCode = "34000" }
};
}
[Fact]
public void CalculateShipping_ForPremiumCustomer_ReturnsFreeShipping()
{
var customer = new CustomerBuilder().AsPremium().Build();
var service = new ShippingService();
var cost = service.CalculateShipping(customer);
Assert.Equal(0, cost);
}
5. Parametreli Testleri Tekrarlamak¶
❌ Yanlış Kullanım: Farklı girdiler için aynı testi kopyalamak.
[Fact]
public void IsValid_WithEmptyEmail_ReturnsFalse()
{
Assert.False(EmailValidator.IsValid(""));
}
[Fact]
public void IsValid_WithNoAtSign_ReturnsFalse()
{
Assert.False(EmailValidator.IsValid("test.com"));
}
[Fact]
public void IsValid_WithNoDomain_ReturnsFalse()
{
Assert.False(EmailValidator.IsValid("test@"));
}
✅ İdeal Kullanım: [Theory] ve [InlineData] ile parametreli test yazın.
[Theory]
[InlineData("")]
[InlineData("test.com")]
[InlineData("test@")]
[InlineData("@domain.com")]
[InlineData("test @domain.com")]
public void IsValid_WithInvalidEmail_ReturnsFalse(string email)
{
Assert.False(EmailValidator.IsValid(email));
}
[Theory]
[InlineData("test@domain.com")]
[InlineData("user.name@domain.co")]
public void IsValid_WithValidEmail_ReturnsTrue(string email)
{
Assert.True(EmailValidator.IsValid(email));
}
6. Exception Testlerini Yanlış Yazmak¶
❌ Yanlış Kullanım: Try-catch ile exception test etmek.
[Fact]
public void Withdraw_InsufficientFunds_ThrowsException()
{
try
{
var account = new BankAccount(100);
account.Withdraw(200);
Assert.True(false, "Exception bekleniyor");
}
catch (InsufficientFundsException)
{
Assert.True(true);
}
}
✅ İdeal Kullanım: Assert.Throws ile temiz exception testi yazın.
[Fact]
public void Withdraw_WhenAmountExceedsBalance_ThrowsInsufficientFundsException()
{
var account = new BankAccount(100);
var exception = Assert.Throws<InsufficientFundsException>(
() => account.Withdraw(200));
Assert.Equal("Yetersiz bakiye.", exception.Message);
}