如何进行单元测试的BeginInvoke上的操作 [英] How to Unit Test BeginInvoke on an Action

查看:123
本文介绍了如何进行单元测试的BeginInvoke上的操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要寻找一种方式来测试的BeginInvoke上的操作方法,因为该方法运行在后台线程就没有办法知道它实际上完成或调用回调方法的时候。我正在寻找一种方法来保持我的测试等到回调作出断言之前被调用。

在以下presenter类,你可以看到,我调用PopulateView在后台线程用于更新视图时,数据被取出,我试图断言视图属性被正确初始化。

我使用NUnit和起订量。

 公共类presenter
{
    私人IVIEW _view;
    私人IService _Service;
    公共presenter(IVIEW观点,IService服务)
    {
        _view =图。
        _Service =服务;

        动作动作= PopulateView;
        action.BeginInvoke(PopulateViewCallback,动作);
    }
    私人无效PopulateViewCallback(IAsyncResult的AR)
    {
            尝试
            {
                行动目标=(动作)ar.AsyncState;
                target.EndInvoke(AR);
            }
            赶上(例外前)
            {
                Logger.Instance.LogException(初始化失败观,前);
            }
    }

     私人无效PopulateView()
     {
          Thread.sleep代码(2000); //获取数据_service.DoSomeThing()
          _view.Property1 =XYZ;
     }
}
 

解决方案

摘要您code,这样你可以注入你想要的行为的测试时间。

 公共类MethodInvoker
{
    公共虚拟无效的InvokeMethod(操作方法,操作回调)
    {
         method.BeginInvoke(回调,法);
    }
}
 

这个版本是异步的。在测试的时候,你可以简单地做一个堵版:

 公共类TestInvoker
{
    公众的IAsyncResult MockResult {获得;组; }

    公众覆盖无效的InvokeMethod(操作方法,操作回调)
    {
         方法();
         回调(MockResult);
    }
}
 

那么你的code简单地改变这样的:

  //注入​​这种依赖性
Invoker.InvokeMethod(PopulateView,PopulateViewCallback);
 

在运行时,它是异步的。在测试时,它会阻止呼叫。

I am looking for a way to test BeginInvoke on an Action method, since the method runs on a background thread there is no way of knowing when it actually completes or calls callback method. I am looking for a way to keep my test wait until the callback gets called before making assertions.

In the following Presenter class, you can notice that I am invoking PopulateView on background thread which updates the view when data is fetched and I am trying assert the view Properties are correctly initialized.

I am using NUnit and Moq.

public class Presenter
{
    private IView _view;
    private IService _service;
    public Presenter(IView view, IService service)
    {
        _view = view;
        _service = service;

        Action action = PopulateView;  
        action.BeginInvoke(PopulateViewCallback, action);
    }
    private void PopulateViewCallback(IAsyncResult ar)
    {
            try
            {
                Action target = (Action)ar.AsyncState;
                target.EndInvoke(ar);
            }
            catch (Exception ex)
            {
                Logger.Instance.LogException("Failed to initialize view", ex);
            }
    }

     private void PopulateView()
     {
          Thread.Sleep(2000); // Fetch data _service.DoSomeThing()
          _view.Property1 = "xyz";
     }  
}

解决方案

Abstract your code so that you can inject the behavior you want at testing time.

public class MethodInvoker
{
    public virtual void InvokeMethod(Action method, Action callback)
    {
         method.BeginInvoke(callback, method);
    }
}

This version is asynchronous. At testing time, you can simply make a blocking version:

public class TestInvoker
{
    public IAsyncResult MockResult { get; set; }

    public override void InvokeMethod(Action method, Action callback)
    {
         method();
         callback(MockResult);
    }
}

Then your code simply changes to this:

 // Inject this dependency
Invoker.InvokeMethod(PopulateView, PopulateViewCallback);

At runtime, it's asynchronous. At testing time, it blocks the call.

这篇关于如何进行单元测试的BeginInvoke上的操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆