Moq kütüphanesinin Mock sınıfları oluşturulurken varsayılan davranış şekli Loose'dur. Bu şekilde tanımlanan mock nesneleri metot çağrıları için kurulum zorunluluğu dayatmaz.
var loggingService =newMock<ILoggingService>();var loggingService =newMock<ILoggingService>(MockBehavior.Loose);
Strict Mock bir mock nesnenin çalışması için setup işleminin yapılmasını zorunlu kılar.
var loggingService =newMock<ILoggingService>(MockBehavior.Strict);
Yararlar
Bu kullanım aşağıdaki yararlara sahiptir:
1. Doğrulanması unutulan metot çağrılarını (Verify) tespit eder.
void metotların çalışıp çalışmadığı kontrol edilmelidir.
Strict Mock kullanılmadığı durumlarda bu kontrol ancak Verify çağrısı ile sağlanır.
Assert bölümünde Verify çağrısı unutulursa test edilen metodun tüm davranışları test edilmemiş olur.
Strict Mock her çağrılan mock nesne metodunun setup'ını zorunlu kıldığından bu metotların da setupları yapılır.
Setup'ı yapılıp çalışmayan mock nesne metodu aşağıdaki hatayı oluşturur.
Moq.MockException: Mock<ISecurityService:1>:This mock failed verification due to the following: ISecurityService x =>x.Encrypt(): This setup was not matched.
Çalıştığı doğrulanmak istenen metot kurulumu için Verifiable() olarak işaretlenir.
Metotlarının kurulumları yapılan mock nesne Assert bölümünde Verify() metodu çağrısı ile doğrulanmalıdır.
securityService.Verify();
Metotların kurulumunda Verifiable çağrısı yapılmadan, mock nesnenin tüm çağrılarının (Verifiable veya değil) doğrulamasını sağlamak için VerifyAll() metodu kullanılır. (Önerilen pratik budur)
securityService.VerifyAll();
2. Çalışmaması gereken metot çağrılarını tespit eder.
Çağrılan her metodun setup'ı yapılmalıdır.
Setup'ı yapılmayan bir metot çağrıldığında aşağıdaki hata alınır:
Moq.MockException:ISecurityService.CreateHash("foo") invocation failed with mock behavior Strict.All invocations on the mock must have a corresponding setup.
3. Assert bölümlerinde Verify işlemleri sadeleşir
Verify edilmesi gereken metotların kurulumları da Arrange bölümünde yapıldığından Assert bölümün daha sade ve anlaşılır hale gelir.
4. Metodun fazla sorumluluğu varsa bunu önplana çıkarır
Doğrulanması gereken çağrılar için setup gerektiğinden, setup'ın ve test edilen metodun büyüklüğü gözle görülür hale gelir.
Büyük bir test kurulum bölümü, test edilen metodun gerektiğinden fazla sorumluluğa sahip olduğunun ve yeterince soyutlama yapılmadığının göstergesidir.
Extract Class veya Move Method yöntemleri uygulanabilir.
Uygulama Örneği
TestFixture sınıfları Foo.Framework.UnitTests v2.0 nuget paketinde bulunan BaseTestFixture sınıfından türetilir.
BaseTextFixture sınıfı
namespaceFoo.Framework.UnitTests{ /// <summary> /// Fixture sınıfları için temel sınıf. Strict Mock kullanımını zorunlu kılar. Teardown metodunda VerifyMocks işlemi içerir.
/// </summary>publicabstractclassBaseTestFixture:TestFixture { /// <summary> /// VerifyMocks metodunu tetikleyen işlemi. TestFixture'da tanımlanan tüm mock nesnelerin Verify edilmesi hedeflenir.
/// </summary> [TearDown]publicvoidTearDown() {VerifyMocks(); } /// <summary> /// TestFixture'da tanımlanan tüm mock nesnelerin Verify edilmesini hedefleyen soyut metot. /// Mock nesnelerin VerifyAll() metodunun çağrılması beklenir. /// </summary>protectedabstractvoidVerifyMocks(); }}
BaseTestFixture sınıfı her testten sonra çalışmak üzere TearDown metodunu içerir ve bu metotta VerifyMocks metodu çağrılır.
BaseTestFixture sınıfında bulunan abstract VerifyMocks metodu implemente edilir ve TestFixture'da bulunan tüm mock memberlar için VerifyAll metodu çağrılır.
Bu metot bir mock için yapılan setup işlemi Verifable olarak işaretlenip işaretlenmeme durumuna bakmaksızın mock nesne için Verify işlemini uygular.
Testlerde Arrange bölümünde setup işlemlerini Verifiable olarak işaretlemek ve Assert bölümünde mocklar için Verify veya VerifyAll çağrısı yapmaya gerek yoktur.
Mock member içermeyen TestFixture sınıflarında mock Verify işlemine gerek olmadığından bu sınıflar BaseTestFixture yerine LooseBaseTestFixture sınıfından türetilirler.
Bu sınıf bir TearDown metodu ve abstract VerifyMocks metodu içermez.
namespaceFoo.Framework.UnitTests{ /// <summary> /// Strict Mock kullamının gerekmediği TestFixture sınıfları için temel sınıf. /// </summary>publicclassLooseBaseTestFixture:TestFixture { }}
usingMoq;namespaceFoo.Framework.UnitTests{ /// <summary> /// Birim testleri Fixture sınıfları için temel sınıf. /// </summary>publicabstractclassTestFixture {#regionverify any /// <summary> /// Moq.Mock sınıfları için Verify işlemi uygulandığında geçirilen It.IsAny tipinde parametreler için kullanılır.
/// It.IsAny metodunun hangi bağlamda kullanıldığını tespit etmek amacıyla oluşturulmuştur. /// </summary> /// <typeparamname="T">Any olarak kullanılacak tip bilgisi</typeparam> /// <returns></returns>publicstaticTVerifyAny<T>() {returnAny<T>(); }#endregion#regionsetup any /// <summary> /// Moq.Mock sınıfları için Setup işlemi uygulandığında geçirilen It.IsAny tipinde parametreler için kullanılır.
/// It.IsAny metodunun hangi bağlamda kullanıldığını tespit etmek amacıyla oluşturulmuştur. /// </summary> /// <typeparamname="T">Any olarak kullanılacak tip bilgisi</typeparam> /// <returns></returns>publicstaticTSetupAny<T>() {returnAny<T>(); }staticTAny<T>() {returnIt.IsAny<T>(); }#endregion }}