Tamam - Aşağıdakilerin size herhangi bir yardımı olup olmayacağından emin değilim, çünkü sizin durumunuzda doğru olan veya olmayan bir çözüm geliştirme konusunda bazı varsayımlar yaptım. Belki benim "çözümüm" çok teorik ve sadece yapay örnekler için çalışıyor - aşağıdakilerin ötesinde herhangi bir test yapmadım.
Ek olarak, aşağıdakileri gerçek bir çözümden çok daha fazla geçici bir çözüm olarak görecektim, ancak yanıtların eksikliğini düşünerek hala hiçbir şeyden daha iyi olabileceğini düşünüyorum (sorunuzu bir çözüm beklerken izlemeye devam ettim, ancak birisinin yayınlandığını görmeden oynamaya başladım. sorunu etrafında).
Ancak yeterli sayıda şey söylendi: Diyelim ki bir tamsayı almak için kullanılabilecek basit bir veri servisimiz var:
public interface IDataService
{
Task<int> LoadMagicInteger();
}
Basit bir uygulama asenkron kod kullanır:
public sealed class CustomDataService
: IDataService
{
public async Task<int> LoadMagicInteger()
{
Console.WriteLine("LoadMagicInteger - 1");
await Task.Delay(100);
Console.WriteLine("LoadMagicInteger - 2");
var result = 42;
Console.WriteLine("LoadMagicInteger - 3");
await Task.Delay(100);
Console.WriteLine("LoadMagicInteger - 4");
return result;
}
}
Şimdi, bu sınıfın gösterdiği gibi "yanlış" kodunu kullanıyorsak, bir sorun ortaya çıkıyor. sonucu gibi yapmak yerine Foo
yanlış erişir :Task.Result
await
Bar
public sealed class ClassToTest
{
private readonly IDataService _dataService;
public ClassToTest(IDataService dataService)
{
this._dataService = dataService;
}
public async Task<int> Foo()
{
var result = this._dataService.LoadMagicInteger().Result;
return result;
}
public async Task<int> Bar()
{
var result = await this._dataService.LoadMagicInteger();
return result;
}
}
Şimdi (size) ihtiyacımız olan şey, arama yaparken başarılı olan Bar
ancak arama yaparken başarısız olan bir sınama yazmaktır Foo
(en azından soruyu doğru anladıysam ;-)).
Kodun konuşmasına izin vereceğim; İşte ne buldum (Visual Studio testleri kullanarak, ama NUnit kullanarak da çalışması gerekir):
DataServiceMock
kullanır TaskCompletionSource<T>
. Bu, sonucu test çalışmasında tanımlanmış bir noktaya koymamızı sağlar ve bu da aşağıdaki teste neden olur. TaskCompletionSource'u teste geri döndürmek için bir temsilci kullandığımızı unutmayın. Bunu, testin Başlat yöntemine ve kullanım özelliklerini de koyabilirsiniz.
TaskCompletionSource<int> tcs = null;
this._dataService.LoadMagicIntegerMock = t => tcs = t;
Task<int> task = null;
TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Foo());
tcs.TrySetResult(42);
var result = task.Result;
Assert.AreEqual(42, result);
this._end = true;
Burada olan, ilk önce yöntemi engellemeden bırakabileceğimizi doğrulamamızdır (bu, eğer biri erişirse işe yaramaz Task.Result
- bu durumda, görev sonucu yöntem geri dönene kadar müsait olmadığından zaman aşımına uğrarız) ).
Ardından sonucu belirledik (şimdi yöntem çalışabilir) ve sonucu doğrularız (bir birim testinde Task.Result'a erişebiliriz, aslında engellemenin gerçekleşmesini istiyoruz ).
Komple test sınıfı - istendiğinde BarTest
başarılı ve FooTest
başarısız.
[TestClass]
public class UnitTest1
{
private DataServiceMock _dataService;
private ClassToTest _instance;
private bool _end;
[TestInitialize]
public void Initialize()
{
this._dataService = new DataServiceMock();
this._instance = new ClassToTest(this._dataService);
this._end = false;
}
[TestCleanup]
public void Cleanup()
{
Assert.IsTrue(this._end);
}
[TestMethod]
public void FooTest()
{
TaskCompletionSource<int> tcs = null;
this._dataService.LoadMagicIntegerMock = t => tcs = t;
Task<int> task = null;
TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Foo());
tcs.TrySetResult(42);
var result = task.Result;
Assert.AreEqual(42, result);
this._end = true;
}
[TestMethod]
public void BarTest()
{
TaskCompletionSource<int> tcs = null;
this._dataService.LoadMagicIntegerMock = t => tcs = t;
Task<int> task = null;
TaskTestHelper.AssertDoesNotBlock(() => task = this._instance.Bar());
tcs.TrySetResult(42);
var result = task.Result;
Assert.AreEqual(42, result);
this._end = true;
}
}
Ve kilitlenmeleri / zaman aşımlarını test etmek için küçük bir yardımcı sınıf:
public static class TaskTestHelper
{
public static void AssertDoesNotBlock(Action action, int timeout = 1000)
{
var timeoutTask = Task.Delay(timeout);
var task = Task.Factory.StartNew(action);
Task.WaitAny(timeoutTask, task);
Assert.IsTrue(task.IsCompleted);
}
}
async
makale koleksiyonunu okudun mu?