unit testing system.timers.timer

后端 未结 2 1598
情书的邮戳
情书的邮戳 2020-12-15 23:10

I\'ve been reading over the questions about unit testing with timers and threading. I found the SO question about unit testing system.threading.timers, but I need to unit t

相关标签:
2条回答
  • 2020-12-15 23:28

    What stops you from wrapping this one?

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

    That's pretty much all your interface needs. Let's see how this could go (note that you could of course expose more Timer properties, but that's pretty much basic stuff that should be enough):

    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; }
        }
    }
    

    Now, how would you utilize this in your testing (assuming we're using FakeItEasy as mocking framework of choice):

    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);
    

    Example above actually does test the code that happens once the event on timer is raised. Consider MyClass looking like this:

    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;
        }
    }
    

    In the test, we force timer to raise when we need it, and we check whether code in TimerElapsedHandler executed, by asserting ReceivedEvent property was set. In reality, this method might do more than that, but that will only change the way we do assertions - idea remains the same.


    Edit: You can also try Moles, a framework that allows you to generate fakes of any framework types/methods. However, if mocking timer was all you wanted, I'd go with wrapper approach.

    0 讨论(0)
  • 2020-12-15 23:32

    You need to test the timer or test the code executed in each event? If so, you can put that logic in another class and just test that. You can trust the timer will call it...

    0 讨论(0)
提交回复
热议问题