2013-06-13 12 views
5

Özel bir SynchronizationContext uygulamasının etrafında birim testleri yazmaya çalışıyorum.Bu uygulamaların, gerektiğinde nerede senkron veya asenkron olduğunu nasıl test edebilirim?

Bu sınıfa iki önemli operasyonlar Send bir temsilci eşzamanlı çağırır ve Post uyumsuz bir temsilci çağırır Send ve Post vardır.

Bu davranışı doğrulamak için delegelerin eşzamanlı veya eşzamansız olarak yürütüldüğünü doğrulamak için birim sınamaları yazmak istiyorum. Testlerin başarı durumları için gecikmelere dayanmasını istemiyorum, çünkü yapay olarak testlerin çalışmasını uzatıyor (ancak başarısızlıkların olması gecikmeye neden oluyor).

Başlangıçta bir temsilci yürütülmesini sinyal Görevler olarak bulunması

var tcs = new TaskCompletionSource<object>(); 

var context = new CustomSynchronizationContext(); 

context.Send((state) => tcs.SetResult(null), null); 

// Task should already be completed! 
Assert.IsTrue(this.tcs.Task.IsCompleted); 

Ancak bu çok hızlı bir test atlet devam edemeden uyumsuz idam değildi temsilci garantilemez.

nasıl Send delege tamamlanması için bloklar ve Post olmadığından emin olmak için bağlam etrafında bir test sağlayabilir, ancak olan delegeler hem çağrılan mı?

+1

+1 ... :) –

+0

Isn Temsilci üzerinde yürütülen Thread.ManagedThreadId 'bir geri gönderme yapmak mümkün mü? Ana iş parçacığıyla aynı olsaydı, eşzamanlı olarak yürütüldü, aksi halde eşzamansız. – Davio

+0

Senkronizasyon bağlamı, arama iş parçacığı üzerinde herhangi bir temsilci çalıştırmaz, dolayısıyla korkmuyorum. Konular sadece bir uygulama detayıdır. –

cevap

-1

fikrimi birleştirilerek: bu aslında çalışırsa

var mainThreadId = Thread.ManagedThreadId; 
var sendThreadId; 
context.Send((state) => sendThreadId = Thread.ManagedThreadId); 
Assert.AreEqual(mainThreadId, sendThreadId); 

Bilmiyorum, denetlemek gerekir.

+0

Senkronizasyon bağlamı çağrı iş parçacığı üzerinde herhangi bir temsilci çalıştırmaz, bu yüzden korkmuyorum. Konular, eşzamansız programlamada sadece bir uygulama ayrıntısıdır. –

+0

Evet, “eşzamanlı” ve “senkronize olmayan”, “aynı iş parçacığı” ve “başka bir iş parçacığı” ile aynı değildir. Eşzamanlı yöntem başka bir iş parçacığı üzerinde temsilci çalıştırabilir ve eşzamanlı olarak bitirmesini bekleyebilir. – svick

3

Bunu bir çift ManualResetEvents kullanarak gerçekleştirebileceğinizi düşünüyorum. Aşağıdaki kodu kullanarak, yavaşlama sadece testler başarısız olduğunda yaşanır (sayılar oldukça yüksektir ve muhtemelen güvenli bir şekilde azaltılabilir). Buradaki fikir, yalnızca engellersek veya engellemediğimizde gerçekleşebilecek şeylerin gerçekleşmesi gereken düzeni iddia etmemizdir. Zaman uyumsuz testi için

var incall = new ManualResetEvent(false); 
var unblock = new ManualResetEvent(false); 
var context = new CustomSynchronizationContext(); 
var t = Task.Run(() => context.Send(state => 
{ 
    incall.Set(); 
    unblock.WaitOne(5000); 
}, null)); 
Assert.IsTrue(incall.WaitOne(1000)); 
Assert.IsFalse(t.Wait(10)); 
unblock.Set(); 
Assert.IsTrue(t.Wait(1000)); 

: senkron testi için

sorusuna ve Adı "trajedik" sorunları çözmek bir kişi için

var incall = new ManualResetEvent(false); 
var unblock = new ManualResetEvent(false); 
var context = new CustomSynchronizationContext(); 
var t = Task.Run(() =>context.Post(state => 
{ 
    incall.Set(); 
    unblock.WaitOne(5000); 
}, null)); 
Assert.IsTrue(incall.WaitOne(1000)); 
Assert.IsTrue(t.Wait(1000)); //This will timeout if unblock is blocking completion of the task 
unblock.Set(); 
+0

Ancak zamanlama doğruysa, senkronize olmayan bir yöntem senkronize testinizi geçirebilir. – svick

+0

Engellemenin daha önce zaman aşımına uğrayabileceğini ve görev son kontrol veya başka bir sorundan önce tamamlandığını mı söylüyorsunuz? – jageall

+0

Hayır, ikinci 'Assert()' sırasında, eşzamansız yöntem yürütmeyi zaten başlatmış olabilir (bu nedenle 'incall.WaitOne()' hemen tamamlanır), ancak henüz geri dönmemiş olabilir, 'Durum' yine de olacaktır Running'. – svick

İlgili konular