2012-06-30 9 views
5

Powiedzmy mam trochę APM (BeginXxx, EndXxx) METODY wzór asynchroniczny (jako część jakiegoś pełnomocnika usług WCF Dzwonię):Jak skonfigurować wywołanie metody BeginXXX EndXXX za pomocą moq?

public interface ISomeService 
{ 
    IAsyncResult BeginSomeMethod(int num, AsyncCallback callback, object state); 
    int EndSomeMethod(IAsyncResult ar); 
} 

Moje rzeczywisty kod wykorzystuje używa Task.Factory.FromAsync Aby utworzyć zadanie, a następnie oczekując na to zadanie, używając nowego wzoru async/await wprowadzonego w .net 4.5.

Chciałbym przetestować moją klasę, a tym samym muszę napisać metodę, która odbiera makietę, metodę początkową, metodę końca i wartość zwracaną oraz konfiguruje próbę tak, aby w końcu zwracała wymaganą wartość zwracaną.

przykład użycia:

SetupAsync(mock, mocked => mocked.BeginSomeMethod, mocked=> mocked.EndSomeMethod, 7); 

co spowoduje przepływ asynchronicznej z dowolnego int argument do powrotu 7. I nie wydaje się dowiedzieć się, jak osiągnąć coś takiego w MOQ.

Odpowiedz

6

Po pierwsze, zalecam użycie TaskWsdlImportExtension do tworzenia asynchronicznych proxy WCF z Task. VS2012 robi to domyślnie, ale ty have to set it up yourself na VS2010 + AsyncCTP. Łatwiej jest testować jednostki pod kątem interfejsu API Task.

Jeśli chcesz testów jednostkowych przed Begin/End, myślę, że najłatwiejszym sposobem będzie użycie Task opartych mocks i narazić Begin/End punktów końcowych. Metody [AsyncFactory|AsyncFactory<T>].[ToBegin|ToEnd] w mojej bibliotece dostarczają wrappery metod wokół Task lub można zobaczyć Stephen Toub's blog post about writing these kinds of wrappers.

Można uzyskać proste już wykonanych zadań z Task.FromResult, czy można stosować następujące konstruktu aby wymusić asynchronicznie wypełnione zadanie:

Task.Run(async() => { await Task.Yield(); return 7; }); 

(odpowiednik asynchroniczny CTP będzie BE):

TaskEx.RunEx(async() => { await TaskEx.Yield(); return 7; }); 

Nie jestem do końca pewien, jak powiązać to z Moq. Ponownie, podejrzewam, że interfejs API oparty na Task byłby łatwiejszy do podrobienia niż Begin/End. Begin/End ma swoją własną specjalną semantykę (musisz podać poprawną IAsyncResult, End musi być wywołana dokładnie jeden raz dla każdego Begin itd.), Więc jest jeszcze więcej rzeczy do przetestowania.

+0

+1 dla TaskWsdlImportExtension. –