Ufu*_*arı 14 .net c# moq event-handling
我试图触发分配给我的计时器模拟的事件处理程序.我如何在这里测试这个私有方法?
public interface ITimer
{
void Start();
double Interval { get; set; }
event ElapsedEventHandler Elapsed;
}
Run Code Online (Sandbox Code Playgroud)
客户端类为此对象分配事件处理程序.我想测试这个类中的逻辑.
_timer.Elapsed += ResetExpiredCounters;
Run Code Online (Sandbox Code Playgroud)
分配的方法是私有的
private void ResetExpiredCounters(object sender, ElapsedEventArgs e)
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
我希望在我的模拟中有这个事件处理程序并以某种方式运行它.我怎样才能做到这一点?
更新:
在分配事件处理程序之前,我意识到我正在提升事件.我纠正了这个,但我仍然得到这个错误:
System.ArgumentException : Object of type 'System.EventArgs' cannot be converted
to type 'System.Timers.ElapsedEventArgs'.
Run Code Online (Sandbox Code Playgroud)
我这样举起来:
_timer.Raise(item => item.Elapsed += null, ElapsedEventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)
要么
_timer.Raise(item => item.Elapsed += null, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)
两者都行不通.
更新:
这对我有用.请注意,如果您尝试将信息传递给事件处理程序(如Jon在评论中指出),则无效.我只是用它来模拟System.Timers.Timer类的包装器.
_timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs);
Run Code Online (Sandbox Code Playgroud)
最后,如果你需要使用事件参数,这根本不会有用,因为它总是为null.但是,这是自ElapsedEventArgs只有一个内部构造函数以来的唯一方法.
Joa*_*Fdz 11
ElapsedEventArgs 有一个私有构造函数,无法实例化.
如果您使用:
timer.Raise(item => item.Elapsed += null, new EventArgs() as ElapsedEventArgs);
Run Code Online (Sandbox Code Playgroud)
然后处理程序将接收null参数并丢失其SignalTime属性:
private void WhenTimerElapsed(object sender, ElapsedEventArgs e)
{
// e is null.
}
Run Code Online (Sandbox Code Playgroud)
在某些情况下,您可能需要此参数.
为了解决这个问题并使其更易于测试,我还为它创建了一个包装器ElapsedEventArgs,并使接口使用它:
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();
}
Run Code Online (Sandbox Code Playgroud)
实现将简单地触发自己的事件来获取真实计时器事件中的数据:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以简化和改进此事件的模拟:
timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs());
var yesterday = DateTime.Now.AddDays(-1);
timer.Raise(item => item.Elapsed += null, new TimeElapsedEventArgs(yesterday));
Run Code Online (Sandbox Code Playgroud)
编写更少的代码,更易于使用并完全与框架分离.
该起订量快速入门指南对事件的部分.我想你会用的
mock.Raise(m => m.Elapsed += null, new ElapsedEventArgs(...));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6210 次 |
| 最近记录: |