Модульное тестирование компонента, основанного на времени? - PullRequest
5 голосов
/ 25 июня 2010

Итак, я пишу кеш-систему (не слишком сложную, но с очень хорошей семантикой) с ttl (время жизни) для элементов.

Конечно, ttl должен быть модульно протестирован, но поскольку нельзя внедрить новую реализацию "IDateTime" или "ITimeSpan" в C # (потому что такого нет), как бы вы поступили об этом? *

Сначала напишите новый компонент "IDateTimeProvider" и "DateTimeProvider", какой из них затем можно макетировать?

Не является ли переопределение частей библиотеки времени выполнения .NET ... излишним?

Редактировать: Спасибо всем за ваши удивительные ответы! Теперь я точно знаю, что собираюсь делать!

Ответы [ 5 ]

6 голосов
/ 25 июня 2010

Я обычно использую вариант решение Айенде .

public static class SystemTime
{
    public static Func<DateTime> DateProvider = () => DateTime.Now;

    public static DateTime Now { get { return DateProvider(); } }
}

В тестируемом коде теперь вы можете использовать SystemTime.Now для получения текущего времени:

var currentTime = SystemTime.Now;

А в тесте вы можете установить текущее время на известное значение:

SystemTime.DateProvider = () => new DateTime(2010,6,25);
4 голосов
/ 25 июня 2010

как написание IDateTimeProvider будет переопределять части .Net Framework?

У вас просто две реализации, одна из которых возвращает DateTime.Now, а другая возвращает значение, указанное вами ранее.

3 голосов
/ 25 июня 2010

Возможно, вы захотите увидеть этот вопрос:

Как мне MOQ для класса System.IO.FileInfo ... или любого другого класса без интерфейса?

В двух словах вам нужно либо создать класс-оболочку самостоятельно, либо использовать библиотеку, которая уже предоставляет классы-оболочки для DateTime, например SystemWrapper .

2 голосов
/ 25 июня 2010

Если у вас возникли проблемы при изобретении какого-либо макетного объекта, я думаю, что было бы хорошо переосмыслить тестируемость вашего компонента.

Может быть, логика ttl должна быть тестируемой сама по себе, примерно так:

TTLlogic l = new TTLLogic( 10 );
DateTime startdate = now();
Object item=new String();
l.addItem( startdate, item );

l.setTime( startdate.addSeconds( 5 ) );
assert( l.items().contains( item ) );

l.setTime( startdate.addSeconds( 10 ) );
assert( l.items().empty() );
2 голосов
/ 25 июня 2010

Поставщик IDateTime может оказаться полезным и в других отношениях - если ваш кэш будет использоваться между клиентскими и серверными приложениями, работающими на разных компьютерах, вы будете использовать один и тот же источник времени для обеих машин (обычно для сервера), иначе времяможет быть не в ногу.Если вы используете интерфейс IDateTimeProvider везде, тогда клиент может использовать версию, которая получает время от сервера.

Вы получите плюс разъединение модульного тестирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...