6

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

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

我的实际代码使用Task.Factory.FromAsync.net 4.5 中引入的新异步/等待模式来创建任务,然后等待该任务。

我想测试我的类,因此我需要编写一个方法来接收模拟、开始方法、结束方法和返回值,并设置模拟以便最终返回所需的返回值。

示例用法:

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

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

4

1 回答 1

6

首先,我建议您使用TaskWsdlImportExtensionto create Task-based 异步 WCF 代理。VS2012 默认会这样做,但是你必须在 VS2010+AsyncCTP上自己设置。针对TaskAPI 进行单元测试更容易。

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

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

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

(Async CTP 等效项是):

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

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

于 2012-06-30T14:53:43.910 回答