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

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中引入的新的async/await模式等待此任务。

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

示例用法:

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

当任何整数参数引起异步流返回7时,需要进行翻译。 但我似乎无法弄清楚如何在moq中实现这样的事情。

1个回答

6

首先,我建议您使用TaskWsdlImportExtension创建基于Task的异步WCF代理。VS2012默认情况下会这样做,但是在VS2010+AsyncCTP上,您需要自己设置。使用Task API更容易进行单元测试。

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

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

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

(异步 CTP 的等效物将是):
TaskEx.RunEx(async () => { await TaskEx.Yield(); return 7; });

我不太确定如何将这个内容与Moq相结合。我认为基于Task的API比Begin/End更容易进行模拟。 Begin/End具有自己特殊的语义(必须传递正确的IAsyncResult,每个Begin必须恰好调用一次End等),因此要测试的东西更多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接