假设我有一些APM(BeginXxx,EndXxx)模式异步方法(作为我正在调用的一些WCF服务代理的一部分):
public interface ISomeService
{
IAsyncResult BeginSomeMethod(int num, AsyncCallback callback, object state);
int EndSomeMethod(IAsyncResult ar);
}
我的实际代码使用Task.Factory.FromAsync
创建一个Task,然后使用.net 4.5中引入的新的async / await模式等待此任务。
我想测试我的类,因此我需要编写一个接收mock,begin方法,end方法和返回值的方法,并设置mock以便最终返回所需的返回值。
示例用法:
SetupAsync(mock, mocked => mocked.BeginSomeMethod, mocked=> mocked.EndSomeMethod, 7);
这会导致异步流与任何int参数返回7。 我似乎无法弄清楚如何在moq中完成这样的事情。
答案 0 :(得分:6)
首先,我建议您使用TaskWsdlImportExtension
创建基于Task
的异步WCF代理。 VS2012默认执行此操作,但您在VS2010 + AsyncCTP上have to set it up yourself。对Task
API进行单元测试更容易。
如果您确实希望针对Begin
/ End
进行单元测试,我认为最简单的方法是使用基于Task
的模拟并公开Begin
/ {{ 1}}端点。 AsyncEx库中的End
方法在[AsyncFactory|AsyncFactory<T>].[ToBegin|ToEnd]
周围提供Begin
/ End
方法包装,或者您可以看到Stephen Toub's blog post about writing these kinds of wrappers。
您可以从Task
获取简单的已完成任务,或者您可以使用以下构造来强制执行异步完成的任务:
Task.FromResult
(异步CTP等价物):
Task.Run(async () => { await Task.Yield(); return 7; });
我不完全确定如何将其与Moq联系起来。同样,我怀疑基于TaskEx.RunEx(async () => { await TaskEx.Yield(); return 7; });
的API比Task
/ Begin
更容易模拟。 End
/ Begin
有自己的特殊语义(您必须传递正确的End
,IAsyncResult
必须为每个End
调用一次,等等,所以有更多的东西需要测试。