c#中异步委托调用的单元测试

本文关键字:调用 单元测试 异步 | 更新日期: 2023-09-27 18:07:04

我有一个函数,它创建了一个委托,并在该对象上启动BeginInvoke,另一个函数被传递进来等待EndInvoke:

    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);
}

我想对此进行单元测试,但是当我这样做时,deploymentcomponentthreaddcallback从未被击中,显然也没有EndInvoke调用。我认为这是发生的,因为测试通过之前的异步线程结束,所以线程停止执行之前EndInvoke,但是有一种方法我可以阻止这种情况发生,所以我可以看到EndInvoke被击中?

欢呼,马特

c#中异步委托调用的单元测试

我认为你的基本问题是你没有在DeployComponent方法上暴露任何可以让你跟踪你在那里开始的异步操作的东西。如果您从那里返回IAsyncResult,您可以调用ar.AsyncWaitHandle.WaitOne()等待,直到它完成。

据我所知,AsyncResult有一个标志(IsCompleted),告诉您操作是否正在进行。等待它(例如,最初使用while循环),然后执行断言

您只需要创建一个注入点来将异步调用转换为阻塞调用。例如:

 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,它就变成了阻塞调用。