Chúng tôi đang viết các bài kiểm tra đơn vị cho mã không đồng bộ sử dụng MSTest và Moq.Mocking Async Methods
Vì vậy, chúng tôi có một số mã trông giống như sau:
var moq = new Mock<Foo>();
moq.Setup(m => m.GetAsync())
.Returns(Task.FromResult(10));
Hoặc như thế này trên các dự án đó có một phiên bản mới hơn của Moq
var moq = new Mock<Foo>();
moq.Setup(m => m.GetAsync())
.ReturnsAsync(10);
Nhìn vào thực hiện Moq của ReturnsAsync:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(this IReturns<TMock, Task<TResult>> mock, TResult value) where TMock : class
{
TaskCompletionSource<TResult> completionSource = new TaskCompletionSource<TResult>();
completionSource.SetResult(value);
return mock.Returns(completionSource.Task);
}
Cả hai phương pháp đều có vẻ giống nhau. Cả hai tạo một số TaskCompletionSource
, gọi SetResult
và trả lại Task
Cho đến giờ rất tốt.
Nhưng các phương pháp ngắn hạn async
được tối ưu hóa để hoạt động đồng bộ. Điều này dường như ngụ ý rằng TaskCompletionSource
luôn đồng bộ, điều này dường như cũng gợi ý rằng việc xử lý bối cảnh và mọi vấn đề liên quan có thể xảy ra sẽ không bao giờ xảy ra.
Vì vậy, nếu chúng ta có một số mã đã được thực hiện một số async
không-không, như trộn awaits
, Wait()
và Result
, rằng những vấn đề này sẽ không được phát hiện trong kiểm tra đơn vị.
Có lợi thế nào để tạo phương pháp tiện ích mở rộng luôn kiểm soát được không? Một cái gì đó như:
public async Task<T> ReturnsYieldingAsync<T>(T result)
{
await Task.Yield();
return result;
}
Trong trường hợp này, chúng tôi sẽ có phương pháp được đảm bảo thực thi không đồng bộ.
Lợi thế nhận thức sẽ phát hiện mã không đồng bộ không hợp lệ. Ví dụ, nó có thể bắt bất kỳ deadlocking hoặc ngoại lệ nuốt trong thử nghiệm đơn vị.
Tôi không chắc chắn 100% trường hợp này, vì vậy tôi thực sự muốn nghe những gì cộng đồng nói.
Tôi muốn nói đến 'ReturnsYieldingAsync', nhưng thậm chí nhiều hơn thế, để trải nghiệm deadlocks tiềm năng, bạn cần phải cài đặt bối cảnh đồng bộ hóa trong runners thử nghiệm của bạn, giống như ['AsyncPump'] (http: // blogs. msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx). – Noseratio
Tôi nghĩ bạn nên thử viết một test case chứng minh 1. nó sẽ hoạt động như mong đợi và 2. bạn có thể tạo test test theo trường hợp test 1 chính xác nhưng không bao giờ gọi 'ReturnsYieldingAsync' và thất bại. –
@Noseratio Rất dễ tìm trên 'AsyncPump'. Vấn đề chính tôi nghĩ rằng chúng tôi đang chạy vào là thử nghiệm chạy vào là bối cảnh đồng bộ hóa của thử nghiệm là vô giá trị. Hoán đổi 'AsyncPump' có vẻ là cách để đi như được hiển thị ở đây http: // stackoverflow.com/questions/14087257/how-to-add-sync-context-to-async-test-method – swestner