题 单元测试系统.timers.timer


我一直在阅读有关定时器和线程的单元测试的问题。我找到了关于单元测试system.threading.timers的SO问题,但是我需要对system.timers.timer和包装类进行单元测试,这对于这个问题似乎并不顺利。

我只需要知道如何模拟计时器和/或系统时间,以便对它进行单元测试。我似乎无法在谷歌的任何地方找到这个。

编辑和更新: 有意义的是,如果我通过如下包装来提取计时器,我可以生成一个计时器并使用模拟将其替换为不同的计时器。然后,相关部分将采用我在运行时注入的计时器(原始而不是模拟)并测试它已过去的事件代码。


13
2018-01-31 22:58


起源


由于您没有提供有关要覆盖哪个测试用例以及哪个代码块代表测试用例下的逻辑的任何信息,因此很难提出建议。 - sll
您需要测试计时器或测试每个事件中执行的代码吗?如果是这样,您可以将该逻辑放在另一个类中,然后测试它。您可以信任计时器调用它。 - ivowiblo
@ivowiblo:我不知道如何将你的评论标记为答案,但我认为这是我能找到的最接近问题的实际答案。 - deltree
张贴作为答案 - ivowiblo


答案:


什么阻止你包装这个?

public interface ITimer
{
    void Start(double interval);
    void Stop();
    event ElapsedEventHandler Elapsed;
}

这几乎是你所有的界面需求。让我们看看这是怎么回事(注意你当然可以暴露更多 Timer 属性,但这是非常基本的东西,应该足够了):

public class MyTimer : ITimer
{
    private Timer timer = new Timer();

    public void Start(double interval)
    {
        timer.Interval = interval; 
        timer.Start();
    }

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

    public event ElapsedEventHandler Elapsed
    {
        add { this.timer.Elapsed += value; }
        remove { this.timer.Elapsed -= value; }
    }
}

现在,您将如何在测试中使用它(假设我们正在使用它 FakeItEasy 作为选择的模拟框架):

var timerFake = A.Fake<ITimer>();
var classUnderTest = new MyClass(timerFake);

// tell fake object to raise event now
timerFake.Elapsed += Raise.With<ElapsedEventArgs>(ElapsedEventArgs.Empty).Now;

// assert whatever was supposed to happen as event response, indeed did
Assert.That(classUnderTest.ReceivedEvent, Is.True);

实际上面的例子  测试发生的代码 一旦计时器上的事件被提出。考虑 MyClass 看起来像这样:

public class MyClass
{
    private ITimer timer;

    public MyClass(ITimer timer)
    {
        this.timer = timer;
        this.timer.Elapsed += TimerElapsedHandler;
    }

    public bool ReceivedEvent { get; set; }

    private void TimerElapsedHandler(object sender, ElapsedEventArgs e)
    { 
        ReceivedEvent = true;
    }
}

在测试中,我们  我们需要时提升计时器,我们检查是否有代码 TimerElapsedHandler 通过断言执行 ReceivedEvent 财产设定。实际上,这种方法可能会做得更多,但这只会改变我们做断言的方式 - 想法保持不变。


编辑: 你也可以试试 ,一个允许您生成的框架 假货 任何框架类型/方法。但是,如果你想要的是模拟计时器,我会采用包装方法。


22
2018-01-31 23:10



如果我用这种方式包装它,我如何控制已用事件和/或模拟对象? - deltree
@deltree:你是什么意思 你怎么能控制事件?如果以这种方式包装它,您可以像任何其他界面一样进行模拟。我将添加简单的例子。 - k.m
这次真是万分感谢。这比我实际说的更接近,显然不是我想说的。这是调用计时器的单元测试的好方法,但不是在它过去时运行的代码。 - deltree
@deltree:实际上 不 计时器过去时运行的测试代码 - 请参阅我的编辑。 - k.m
好决定。我猜我的大脑今天没有运作。 - deltree


您需要测试计时器或测试每个事件中执行的代码吗?如果是这样,您可以将该逻辑放在另一个类中,然后测试它。你可以相信计时器会调用它...


2
2018-01-31 23:44