简体   繁体   English

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

[英]Unit test for asynchronous delegate call in c#

I have a function which created a delegated and starts BeginInvoke on that object, with another function being passed in to wait for EndInvoke: 我有一个函数,该函数创建了一个委托并在该对象上启动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);
}

I'd like to unit test this, but when I do so, DeploymentComponentThreadedCallBack never gets hit, and obviously neither does the EndInvoke call. 我想对此进行单元测试,但是当我这样做时,DeploymentComponentThreadedCallBack永远不会受到攻击,并且EndInvoke调用显然也不会受到攻击。 I presume this is happening because the test passes before the asynchronous thread ends, so the thread stops executing before EndInvoke, but is there a way I can stop this happening so I can see that EndInvoke gets hit? 我认为这是由于测试在异步线程结束之前通过而导致的,所以线程在EndInvoke之前停止执行,但是有什么办法可以阻止这种情况的发生,以便我可以看到EndInvoke被击中了吗?

Cheers, Matt 干杯,马特

I think your basic problem is that you're not exposing anything on the DeployComponent method that would let you track the asynchronous operation that you're starting there. 我认为您的基本问题是,您没有在DeployComponent方法上公开任何可让您跟踪从此处开始的异步操作的内容。 If you returned the IAsyncResult from there you could call ar.AsyncWaitHandle.WaitOne() to wait until it completed. 如果从那里返回IAsyncResult ,则可以调用ar.AsyncWaitHandle.WaitOne()等待其完成。

As far as I remember the AsyncResult has a flag ( IsCompleted ) that tells you whether the operation is going on. 据我所记得, AsyncResult有一个标志( IsCompleted ),该标志告诉您操作是否正在进行。 Wait on it (eg primitively with a while loop), and then do your assertions 等待它(例如,最初使用while循环),然后执行断言

You simply need to make an injection point to turn asynchrounous calls into blocking calls. 您只需要做一个注入点,即可将非正常通话变成阻塞通话。 For example: 例如:

 public class MethodInvoker
 {
     public virtual void Invoke(Action begin, Action<IAsyncResult> end)
     {
          begin.BeginInvoke(end, null);
     }
 }

With a unit testing version like so: 使用这样的单元测试版本:

 public class SynchronousInvoker : MethodInvoker
 {
     public override void Invoke(Action begin, Action<IAsyncResult> end)
     {
         begin();
         end();
     }
 }

Then you would write code like so: 然后,您将像这样编写代码:

 _myMethodInvoker.Invoke(pluginExecuteAction, asyncCallback);

Which in the context of your normal functionality, is asynchronous. 在您的正常功能范围内,这是异步的。 In your unit tests, you simply inject the SynchronousInvoker in it's place and it becomes a blocking call. 在单元测试中,您只需在其位置注入SynchronousInvoker,它就会成为阻塞调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM