2012-01-31 2 views
13

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

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

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

+1

Трудно что-то предложить, поскольку вы не предоставили никакой информации о том, какой тестовый сценарий вы хотите закрыть, а какой блок кода представляет собой логику в тестовом примере. – sll

+3

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

+0

@ivowiblo: Я не знаю, как отметить ваш комментарий как ответ, но я думаю, что это самое близкое к реальному ответу на вопрос, который я могу найти. – deltree

ответ

22

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

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


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

+0

, если я оберну его таким образом, как я могу управлять прошедшим событием и/или высмеивать объект? – deltree

+0

@deltree: что вы подразумеваете под * как вы можете контролировать событие *? Если вы завернете его таким образом, вы можете издеваться над ним, как с любым другим интерфейсом.Я добавлю простой пример. –

+0

спасибо за это. Это ближе к тому, что я на самом деле сказал, и явно не то, что я хотел сказать. Это отличный способ модульного теста, который вызывается таймером, но не код, который запускается, когда он истек. – deltree

2

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