DI ve test
DI container ve xUnit testlerini kurarsın.
DI ve test
Reflection keşfi çalışıyor; ancak komutları elle Activator.CreateInstance ile örnekliyoruz. Şimdi küçük bir bağımlılık enjeksiyonu kabı ekleyeceğiz: Container sınıfı Register<T>(string, Func<T>) ile kayıt yapar, Resolve<T>(string) ile örneği döndürür.
Aynı zamanda küçük bir test ekleyeceğiz: TestHelloCommand metodu container'dan "hello" komutunu çözer, çalıştırır ve sonucun "Merhaba" olduğunu denetler. Bu, xUnit yerine geçen bir el yapımı doğrulamadır; proje boyunca tek dosya kalabilmemizi sağlar.
El yapımı test
Gerçek projelerde test ayrı bir derlemede xUnit ile yazılır. Burada tek dosya kalmak için TestHelloCommand statik metodunu yazıyoruz: container'dan komutu çözer, ExecuteAsync().Result ile sonucu alır ve if (result != "Merhaba") throw new Exception(...) ile doğrular. Başarılıysa Console.WriteLine("Test passed: hello") yazar.
Bu yapı, gerçek bir test çerçevesinin yaptığını küçük ölçekte taklit eder: doğrulama, başarısızlıkta istisna, başarıda bildirim. Birim testi alışkanlığını tek dosyada sürdürmek için pratik bir yoldur.
Uygulama Container ve test ekle
Bir Container sınıfı tanımla; özel Dictionary<string, Func<ICommand>> _factories alsın. Register<T>(string name, Func<T> factory) where T : class, ICommand metodu fabrikayı kayıt altına alsın; Resolve<T>(string name) where T : class metodu fabrikayı çağırıp sonucu (T) türüne çevirsin. Main'de bir Container yarat, Register<ICommand>("hello", () => new HelloCommand()) ile kayıt yap, TestHelloCommand(container) çağır, sonra Resolve<ICommand>("hello") ile komutu çöz ve await cmd.ExecuteAsync() sonucunu yazdır. TestHelloCommand metodu Resolve<ICommand>("hello") ile komutu çözsün, ExecuteAsync().Result ile sonucu alsın, "Merhaba" dışında ise throw new Exception(...) fırlatsın, değilse Console.WriteLine("Test passed: hello") yazsın.
Örnek çözümü göster
class Container { private readonly Dictionary<string, Func<ICommand>> _factories = new(); public void Register<T>(string name, Func<T> factory) where T : class, ICommand => _factories[name] = () => factory(); public T Resolve<T>(string name) where T : class => (T)_factories[name](); } yaz. Main'de: var container = new Container(); container.Register("hello", () => new HelloCommand()); TestHelloCommand(container); var cmd = container.Resolve<ICommand>("hello"); Console.WriteLine(await cmd.ExecuteAsync()); static void TestHelloCommand(Container container) { var cmd = container.Resolve<ICommand>("hello"); var result = cmd.ExecuteAsync().Result; if (result != "Merhaba") throw new Exception($"Beklenen: Merhaba, gerçek: {result}"); Console.WriteLine("Test passed: hello"); }
Örnek çözüm:
using System;
using System.Threading.Tasks;
using System.Reflection;
using System.Collections.Generic;
[Command("hello")]
class HelloCommand : ICommand
{
public async Task<string> ExecuteAsync()
{
await Task.CompletedTask;
return "Merhaba";
}
}
class CommandAttribute : Attribute
{
public string Name { get; }
public CommandAttribute(string name) => Name = name;
}
interface ICommand
{
Task<string> ExecuteAsync();
}
class Container
{
private readonly Dictionary<string, Func<ICommand>> _factories = new();
public void Register<T>(string name, Func<T> factory) where T : class, ICommand =>
_factories[name] = () => factory();
public T Resolve<T>(string name) where T : class => (T)_factories[name]();
}
class Program
{
static async Task Main()
{
var container = new Container();
container.Register("hello", () => new HelloCommand());
TestHelloCommand(container);
var cmd = container.Resolve<ICommand>("hello");
Console.WriteLine(await cmd.ExecuteAsync());
}
static void TestHelloCommand(Container container)
{
var cmd = container.Resolve<ICommand>("hello");
var result = cmd.ExecuteAsync().Result;
if (result != "Merhaba")
throw new Exception($"Beklenen: Merhaba, gerçek: {result}");
Console.WriteLine("Test passed: hello");
}
}
Kendini test et
-
DI kayıt çağrısını tamamla
container.Register____<ICommand>("hello", () => new HelloCommand());Cevabı göster
container.Register<ICommand><ICommand>("hello", () => new HelloCommand()); -
Container.Resolve<T>("hello") ne döndürür?
- HelloCommand türünü
- Kayıtlı fabrikadan oluşturulmuş ICommand örneğini
- Bir Type nesnesini
- Boş bir referansı
Cevabı göster
Bir Type nesnesini — Doğru. Resolve<T> kayıtlı fabrikayı çağırıp ICommand örneğini döndürür.
-
DI ve test terimlerini eşleştir
- Container
- Kayıt ve çözme kabı
- Register<T>
- Fabrika kaydı
- Resolve<T>
- Örnek çözme
- TestHelloCommand
- Doğrulama metodu