CodeBlanks Logo Icon CodeBlanks

Mock

C# kursu · İleri seviye · Ders 71/83

Moq ile sahte nesne (mock) kullanmayı öğrenirsin.

Mock ve Moq

Bazı sınıflar dış bağımlılıklara (e-posta, veritabanı, saat) dayanır. Bunları gerçek ortamda çalıştırmak yavaş veya olanaksızdır. Mock, bağımlılığın davranışını taklit eden sahte bir nesnedir; Moq ise bunu üreten popüler kütüphanedir.

Mock<IEmailService> bir sahte e-posta servisi yaratır. .Setup(...) çağrıları davranışı yapılandırır; .Object gerçek gibi davranan örneği döndürür; test sonunda .Verify(...) çağrıların yapılıp yapılmadığını denetler.

Setup, Object ve Verify

Moq'un üç temel API'si şöyledir: mock.Setup(s => s.Send(It.IsAny<string>())) çağrıya karşılık dönüş değeri ya da yan efekt tanımlar; mock.Object ürün koduna enjekte edilen sahte örneği verir; mock.Verify(s => s.Send("x")) çağrının gerçekleştiğini denetler.

Bu üçlü, "şu metodu şu parametreyle çağırırsan şunu döndür" ve "şu metodu çağırdın mı?" sorularını yanıtlar. Test böylece hem davranışı hem de çağrı gerçeğini denetler.

Uygulama OrderService için Mock kullan

IEmailService arayüzünü void Send(string to) metoduyla tanımla. OrderService sınıfı kurucudan bir IEmailService alsın; PlaceOrder(string customer) metodu servisin Send(customer) metodunu çağırsın. Mock<T> sınıfı (where T : class) kurucudan bir T örneği alsın, Object özelliği bu örneği döndürsün ve Setup() metodu boş bir gövdeye sahip olsun. FakeEmail : IEmailService sınıfı Called bayrağını Send'de true yapsın. OrderServiceTests.TestPlaceOrderCallsEmail metodu [Fact] ile işaretlenip bir Mock<IEmailService> yaratsın, Setup() çağırsın, OrderService'e mock.Object versin, PlaceOrder("Ayşe") çağırsın ve Assert.True(fake.Called) yapsın. Main testi çağırıp "Test passed: Mock email" yazsın.

Örnek çözümü göster
interface IEmailService { void Send(string to); } tanımla. class OrderService { private readonly IEmailService _email; public OrderService(IEmailService e) => _email = e; public void PlaceOrder(string c) => _email.Send(c); } yaz. class Mock<T> where T : class { public T Object { get; } public Mock(T instance) => Object = instance; public void Setup() { } } yaz. class FakeEmail : IEmailService { public bool Called; public void Send(string to) => Called = true; } yaz. class FactAttribute : Attribute { } ve static class Assert { public static void True(bool c) { if (!c) throw new Exception(); } } tanımla. class OrderServiceTests { [Fact] public void TestPlaceOrderCallsEmail() { var fake = new FakeEmail(); var mock = new Mock<IEmailService>(fake); mock.Setup(); var svc = new OrderService(mock.Object); svc.PlaceOrder("Ayşe"); Assert.True(fake.Called); } } yaz. Main'de: var t = new OrderServiceTests(); t.TestPlaceOrderCallsEmail(); Console.WriteLine("Test passed: Mock email");
Örnek çözüm:
using System;

interface IEmailService
{
    void Send(string to);
}

class OrderService
{
    private readonly IEmailService _email;
    public OrderService(IEmailService email) => _email = email;
    public void PlaceOrder(string customer) => _email.Send(customer);
}

class Mock<T> where T : class
{
    public T Object { get; }
    public Mock(T instance) => Object = instance;
    public void Setup() { }
}

class FakeEmail : IEmailService
{
    public bool Called;
    public void Send(string to) => Called = true;
}

class FactAttribute : Attribute { }

static class Assert
{
    public static void True(bool condition)
    {
        if (!condition) throw new Exception("Beklenen: doğru");
    }
}

class OrderServiceTests
{
    [Fact]
    public void TestPlaceOrderCallsEmail()
    {
        var fake = new FakeEmail();
        var mock = new Mock<IEmailService>(fake);
        mock.Setup();
        var service = new OrderService(mock.Object);
        service.PlaceOrder("Ayşe");
        Assert.True(fake.Called);
    }
}

class Program
{
    static void Main()
    {
        var tests = new OrderServiceTests();
        tests.TestPlaceOrderCallsEmail();
        Console.WriteLine("Test passed: Mock email");
    }
}

Kendini test et

  1. Mock (sahte nesne) neden kullanılır?

    • Dış bağımlılığı izole etmek için
    • Daha hızlı derleme için
    • Statik metodları kaldırmak için
    • Daha çok test yazmak için
    Cevabı göster

    Dış bağımlılığı izole etmek için — Doğru. Mock, dış bağımlılığı izole ederek testi hızlı ve deterministik yapar.

  2. Mock örneği oluştur

    var mock = new ____<IEmailService>();
    Cevabı göster
    var mock = new Mock<IEmailService>();
  3. Moq API'lerini eşleştir

    Mock<T>
    Sahte nesne yaratır
    Setup
    Davranışı yapılandırır
    Object
    Sahte örneği döndürür
    Verify
    Çağrıyı denetler

İleri seviye bölümündeki tüm dersler