我怎样才能运行分配给一个模拟的事件处理程序? [英] How can I run the event handler assigned to a mock?

查看:139
本文介绍了我怎样才能运行分配给一个模拟的事件处理程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想火分配给我的定时器模拟事件处理程序。我怎么可以在这里测试这个私有方法

I am trying to fire the event handler assigned to my timer mock. How can I test this private method here?

public interface ITimer
{
    void Start();
    double Interval { get; set; }
    event ElapsedEventHandler Elapsed;
}



客户端类分配一个事件处理这个对象。我想测试这个类中的逻辑

Client class assigns an event handler to this object. I want to test the logic in this class.

_timer.Elapsed += ResetExpiredCounters;

和分配方法是私有的

private void ResetExpiredCounters(object sender, ElapsedEventArgs e)
{
    // do something
}

我想在我的模拟此事件处理程序,并以某种方式运行它。我怎样才能做到这一点。

I want to have this event handler in my mock and run it somehow. How can I do this?

更新:

我意识到我养我分配的事件处理程序之前,该事件。我纠正了,但我仍然得到这个错误:

I realized I was raising the event before I assigned the event handler. I corrected that but I still get this error:

System.ArgumentException : Object of type 'System.EventArgs' cannot be converted 
to type 'System.Timers.ElapsedEventArgs'.



我提出这样的:

I raise it like this:

_timer.Raise(item => item.Elapsed += null, ElapsedEventArgs.Empty);

_timer.Raise(item => item.Elapsed += null, EventArgs.Empty);



双方将无法工作。

Both won't work.

更新:

下面是为我工作的事情。请注意,这不是有用,如果你想传递给事件处理程序,信息像乔恩在评论中指出。 。我只是用它来模拟对System.Timers.Timer类包装

Here's the thing that worked for me. Note that it's not useful if you are trying to pass info to event handler like Jon pointed out in comments. I am just using it to mock the wrapper for System.Timers.Timer class.

_timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs);

在最后,这不会帮助,如果你需要,因为它会使用事件参数都总是空。然而,这是唯一的方法,因为ElapsedEventArgs只有内部构造。

In the end, this won't help at all if you need to use event arguments since it will be always null. However, it's the only way since ElapsedEventArgs has only an internal constructor.

推荐答案

ElapsedEventArgs 拥有一个私人的构造函数,并且不能被实例化

ElapsedEventArgs has a private constructor and can not be instantiated.

如果您使用的:

timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs);



然后,处理程序将recevie一个空参数并失去 SignalTime 属性:

private void WhenTimerElapsed(object sender, ElapsedEventArgs e)
{
    // e is null.
}

您可能需要在某些情况下,这个参数。

You might want this parameter in some cases.

要解决这个问题,并使其更容易测试,我还创建了一个包装的 ElapsedEventArgs ,搞得接口使用它:

To solve this and make it more testable, I also created a wrapper for the ElapsedEventArgs, and made the interface use it:

public class TimeElapsedEventArgs : EventArgs
{
    public DateTime SignalTime { get; private set; }

    public TimeElapsedEventArgs() : this(DateTime.Now)
    {
    }

    public TimeElapsedEventArgs(DateTime signalTime)
    {
        this.SignalTime = signalTime;
    }
}

public interface IGenericTimer : IDisposable
{
    double IntervalInMilliseconds { get; set; }

    event EventHandler<TimerElapsedEventArgs> Elapsed;

    void StartTimer();

    void StopTimer();
}

的实施只会激发自己的事件从现实计时器事件获取数据

The implementation will simply fire its own event getting the data from the real timer event:

public class TimerWrapper : IGenericTimer
{
    private readonly System.Timers.Timer timer;

    public event EventHandler<TimerElapsedEventArgs> Elapsed;

    public TimeSpan Interval
    {
        get
        {
            return this.timer.Interval;
        }
        set
        {
            this.timer.Interval = value;
        }
    }

    public TimerWrapper (TimeSpan interval)
    {
        this.timer = new System.Timers.Timer(interval.TotalMilliseconds) { Enabled = false };
        this.timer.Elapsed += this.WhenTimerElapsed;
    }

    private void WhenTimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
    {
        var handler = this.Elapsed;
        if (handler != null)
        {
            handler(this, new TimeElapsedEventArgs(elapsedEventArgs.SignalTime));
        }
    }

    public void StartTimer()
    {
        this.timer.Start();
    }

    public void StopTimer()
    {
        this.timer.Stop();
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                this.timer.Elapsed -= this.WhenTimerElapsed;
                this.timer.Dispose();
            }

            this.disposed = true;
        }
    }
}

现在,您可以简化和提高本次活动的模拟:

Now, you can simplify and improve the mock of this event:

timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs());

var yesterday = DateTime.Now.AddDays(-1);
timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs(yesterday));



更​​少的代码编写,更易于使用和框架完全解耦。

Less code to write, easier to work with and completely decoupled from the framework.

这篇关于我怎样才能运行分配给一个模拟的事件处理程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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