如何使用moq设置BeginXXX EndXXX方法调用?

ron*_*y l 6 c# wcf asynchronous moq async-await

假设我有一些APM(BeginXxx,EndXxx)模式异步方法(作为我正在调用的一些WCF服务代理的一部分):

public interface ISomeService
{
    IAsyncResult BeginSomeMethod(int num, AsyncCallback callback, object state);
    int EndSomeMethod(IAsyncResult ar);
}
Run Code Online (Sandbox Code Playgroud)

我的实际代码使用了Task.Factory.FromAsync创建一个Task,然后使用.net 4.5中引入的新的async/await模式等待这个任务.

我想测试我的类,因此我需要编写一个接收mock,begin方法,end方法和返回值的方法,并设置mock以便最终返回所需的返回值.

示例用法:

SetupAsync(mock, mocked => mocked.BeginSomeMethod, mocked=> mocked.EndSomeMethod, 7);
Run Code Online (Sandbox Code Playgroud)

这将导致异步流与任何int参数返回7.我似乎无法弄清楚如何在moq中完成这样的事情.

Ste*_*ary 6

首先,我建议您使用TaskWsdlImportExtension创建Task基于异步的WCF代理.VS2012默认执行此操作,但您必须自己在VS2010 + AsyncCTP上进行设置.对TaskAPI 进行单元测试更容易.

如果你想对Begin/ 进行单元测试End,我认为最简单的方法是使用Task基于模拟和公开Begin/ End端点.[AsyncFactory|AsyncFactory<T>].[ToBegin|ToEnd]我的AsyncEx库中的方法提供Begin/ End方法包装器Task,或者你可以看到Stephen Toub关于编写这些包装器的博客文章.

您可以从中获取简单的已完成任务Task.FromResult,或者您可以使用以下构造来强制执行异步完成的任务:

Task.Run(async () => { await Task.Yield(); return 7; });
Run Code Online (Sandbox Code Playgroud)

(异步CTP等价物将是):

TaskEx.RunEx(async () => { await TaskEx.Yield(); return 7; });
Run Code Online (Sandbox Code Playgroud)

我不完全确定如何将其与Moq联系起来.同样,我怀疑Task基于API的模拟比Begin/ 更容易模拟End.Begin/ End有它自己的特殊语义(你必须传递正确的IAsyncResult,End必须为每个都调用一次Begin,等等),所以有更多的东西要测试.