Модульное тестирование system.timers.timer

Я перечитывал вопросы о модульном тестировании с использованием таймеров и потоков. Я нашел вопрос SO о модульном тестировании system.threading.timers, но мне нужно провести модульное тестирование system.timers.timer, и класс-обертка, похоже, не работает так же гладко для этого.

Мне просто нужно знать, как издеваться над таймером и / или системным временем, чтобы выполнить юнит-тестирование против него. Я не могу найти это где-нибудь в Google.

редактировать и обновлять: имеет смысл, что если я извлеку таймер, обернув его, как показано ниже, я могу сгенерировать таймер и использовать насмешку, чтобы заменить его другим таймером. Соответствующая часть заключается в том, чтобы взять тот таймер, который я внедряю во время выполнения (оригинал, а не макет), и проверить его истекший код события.

2 ответа

Решение

Что мешает вам обернуть это?

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 свойство было установлено. На самом деле, этот метод может сделать больше, но это изменит только то, как мы делаем утверждения - идея остается прежней.


Изменить: Вы также можете попробовать Moles, фреймворк, который позволяет генерировать подделки любых типов / методов фреймворка. Однако, если бы таймер насмешки был всем, что вы хотели, я бы использовал подход обертки.

Вам нужно проверить таймер или проверить код, выполняемый в каждом событии? Если это так, вы можете поместить эту логику в другой класс и просто проверить это. Вы можете доверять таймеру вызовет это...

Другие вопросы по тегам