三天来我一直在寻找解决方案。我有这篇文章,但不幸的是,它使用了一个不再可用的库(https://www.codeproject.com/Articles/19597/How-to-Test-a-Class-Which-Uses-DispatcherTimer)。所以我希望有一个新的解决方案,或者更优雅的方法来单元测试使用DispatcherTimer的类。
下面是我的SUT代码:
public class RemainingTimeChangedEventArgs : EventArgs
{
public TimeSpan RemainingTime { get; init; }
public TimeSpan TimerSetFor { get; init; }
}
public class ExtendedTimer
{
public event EventHandler<RemainingTimeChangedEventArgs>? RemainingTimeChanged;
private readonly DispatcherTimer _timer;
private TimeSpan _timerSetFor = TimeSpan.Zero;
private TimeSpan _remainingTime = TimeSpan.Zero;
public TimeSpan Interval
{
get => _timer.Interval;
set => _timer.Interval = value;
}
public ExtendedTimer()
{
_timer = new();
_timer.Tick += OnTimeChanged;
_timer.Interval = TimeSpan.FromSeconds(1);
}
public void Initialize(TimeSpan timerSetFor)
{
_timerSetFor = timerSetFor;
_remainingTime = timerSetFor;
}
public void Start()
{
_timer.Start();
}
public void Resume()
{
_timer.Start();
}
public void Pause()
{
_timer.Stop();
}
public void Stop()
{
_timer.Stop();
}
private void OnTimeChanged(object? sender, EventArgs e)
{
_remainingTime -= Interval;
if (_remainingTime == TimeSpan.Zero) _timer.Stop();
RemainingTimeChanged?.Invoke(this, new RemainingTimeChangedEventArgs
{
RemainingTime = _remainingTime,
TimerSetFor = _timerSetFor
});
}
~ExtendedTimer() {
_timer.Tick -= OnTimeChanged;
}
因此,当用户启动计时器并且TimerSetFor在给定时间内被初始化时,它将引发一个事件来告知每个tick/间隔的剩余时间。一旦剩余时间达到0,它将引发事件并停止计时。
目前,这是我的xUnit测试。我使用任务。延迟,它失败了,因为延迟任务意味着延迟调度器计时器的执行?但我希望它能揭示我的意图:
public class ExtendedTimerTests
{
private readonly ExtendedTimer _sut = new();
[Theory]
[InlineData(10, 100, 10)]
[InlineData(5, 50, 5)]
[InlineData(20, 30, 1)]
public async Task Start_GiveCorrectRemainingTimeEveryIntervalElapsed(
int interval, int timerSetFor, int expectedExecutedFor)
{
_sut.Interval = TimeSpan.FromMilliseconds(interval);
var ticksCount = 0;
void OnSutOnRemainingTimeChanged(object? sender, RemainingTimeChangedEventArgs args)
{
ticksCount++;
}
_sut.RemainingTimeChanged += OnSutOnRemainingTimeChanged;
_sut.Initialize(TimeSpan.FromMilliseconds(timerSetFor));
_sut.Start();
await Task.Delay(TimeSpan.FromMilliseconds(timerSetFor));
Assert.Equal(expectedExecutedFor, ticksCount);
// make sure the ticksCount still the same even after we wait for another time
await Task.Delay(TimeSpan.FromMilliseconds(50));
Assert.Equal(expectedExecutedFor, ticksCount);
}
}
2条答案
按热度按时间wtzytmuj1#
你发布的文章告诉你这个问题:
1.默认情况下,运行单元测试的线程没有活动的Dispatcher
你可以通过注入一个计时器实现来改变你的SUT(ExtendedTimer类),并且不要在你的单元测试中使用DispatcherTimer。
but5z9lq2#
我结束了没有绑定到时间的单元测试,并将DispatcherTimer作为可以注入的依赖项。
测试: