在C#中的异步委托调用单元测试
我有创建了一个委托和对象上开始的BeginInvoke,与其他功能传递在等待EndInvoke会的功能:在C#中的异步委托调用单元测试
private static void DeploymentComponentThreadedCallBack(IAsyncResult ar)
{
var result = (AsyncResult)ar;
var pluginExecuteAction = (Action<int, Guid, int, EnvironmentServerComponentSet, string>)result.AsyncDelegate;
pluginExecuteAction.EndInvoke(ar);
//report back to WCF service that thread is finished
}
public void DeployComponent(byte[] resource, Guid componentGuid, string deploymentType, Dictionary<string, object> args)
{
var asyncCallback = new AsyncCallback(DeploymentComponentThreadedCallBack);
IDeployComponent plugin = GetPluginDelegate();
Action<byte[], Guid, string, Dictionary<string, object>> pluginExecuteAction = plugin.DeployComponent;
IAsyncResult ar = pluginExecuteAction.BeginInvoke(resource, componentGuid, deploymentType, args, asyncCallback, null);
}
我想单元测试这个,但是当我这样做的时候,DeploymentComponentThreadedCallBack永远不会被触发,显然,EndInvoke调用也不会。我认为这是因为在异步线程结束之前测试通过,因此线程在EndInvoke之前停止执行,但是有没有办法阻止这种情况的发生,以便我可以看到EndInvoke被命中?
干杯, 马特
我认为你的基本问题是你没有公开DeployComponent
方法中的任何东西,它可以让你跟踪你从那里开始的异步操作。如果您从那里返回IAsyncResult
,则可以致电ar.AsyncWaitHandle.WaitOne()
等待完成。
至于我记得AsyncResult有一个标志(IsCompleted),告诉您该操作是否是怎么回事。等待它(例如用一个while循环初始化),然后做你的断言
有这样一个标志,但是我如何在调用对象中得到它?即如果DeployComponent方法在Foo对象上,并且在我的测试中,我调用Foo.DeployComponent(byteStream,new Guid(),“cmd”,null);我在哪里得到AsyncResult,看看它是否完成? –
我无法看到你来自哪里。您将AsyncResult传递给第一个方法,因此您可以在传入之前等待它。 – flq
啊我明白你的意思了。这不会起作用,因为在正常情况下,我不想等待它 - 仅用于此测试。否则,不会异步执行该操作。 –
你只需要做一个注入点来将异步调用变成阻塞调用。例如:
public class MethodInvoker
{
public virtual void Invoke(Action begin, Action<IAsyncResult> end)
{
begin.BeginInvoke(end, null);
}
}
有了一个单元测试的版本,像这样:
public class SynchronousInvoker : MethodInvoker
{
public override void Invoke(Action begin, Action<IAsyncResult> end)
{
begin();
end();
}
}
然后你会写代码,像这样:
_myMethodInvoker.Invoke(pluginExecuteAction, asyncCallback);
这在你的正常功能的情况下,是异步。在你的单元测试中,你只需将SynchronousInvoker注入到它的位置,它就成为一个阻塞调用。
这看起来很不错,但我无法调整它使其工作。 BeginInvoke需要AsyncResult类型的参数,而不是Action
不幸的是,这是示例代码 - 实际上,DeployComponent除此之外还有更多的东西,它已经有了一个bool返回类型。 (还是)感谢你的建议。 –
那么你必须以某种方式解决这个问题。如果你想等待一个操作完成,你必须公开一些东西给调用者等待。在正常情况下,你继续,不要等待完成,但在你的测试中,你等待它完成。实际上,只需将DeployComponent更改为遵循APM并在所有启动完成时报告完成。它可能需要一些重构。 – RandomEngy