Свободные утверждения: Использование BeCloseTo в коллекции свойств DateTime
Я обрабатываю несколько элементов, каждый из которых содержит свойство DateProcessed (обнуляемый DateTime) и хочу утверждать, что это свойство установлено на текущую дату. К тому времени, когда он проходит через процедуру обработки, все даты немного различаются.
Я хочу проверить, что все свойства DateProcessed имеют относительный (100 мс) недавний DateTime.
Fluent Assertions имеет метод.BeCloseTo, который отлично работает для одного элемента. Но я хочу использовать это для всей коллекции. Но это не доступно через Contains() при просмотре коллекции.
Упрощенный пример...
[TestFixture]
public class when_I_process_the_items
{
[SetUp]
public void context()
{
items = new List<DateTime?>(new [] { (DateTime?)DateTime.Now, DateTime.Now, DateTime.Now } );
}
public List<DateTime?> items;
[Test]
public void then_first_item_must_be_set_to_the_current_time()
{
items.First().Should().BeCloseTo(DateTime.Now, precision: 100);
}
[Test]
public void then_all_items_must_be_set_to_the_current_time()
{
items.Should().Contain .... //Not sure? :(
}
}
3 ответа
Как прямой ответ на ваш вопрос, вы можете сделать что-то вроде items.Should().OnlyContain(i => (i - DateTime.Now) < TimeSpan.FromMilliseconds(100))
,
Тем не менее, модульный тест, который опирается на DateTime.Now
это очень плохая практика. Что вы можете сделать, это представить что-то вроде этого:
public static class SystemContext
{
[ThreadStatic]
private static Func<DateTime> now;
public static Func<DateTime> Now
{
get { return now ?? (now = () => DateTime.Now); }
set { now = value; }
}
}
Тогда вместо того, чтобы ссылаться на DateTime.Now
использовать SystemContext.Now()
чтобы узнать текущее время. Если вы сделаете это, вы можете "установить" текущее время для конкретного модульного теста, например:
SystemContext.Now = () => 31.March(2013).At(7, 0);
Вы можете сделать это в 3.5, настроив параметры ShouldBeEquivalentTo
, Например:
result.ShouldBeEquivalentTo(expected, options =>
{
options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
return options;
});
или кратко:
result.ShouldBeEquivalentTo(expected, options => options.Using<DateTimeOffset>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTimeOffset>());
Если вы хотите настроить это глобально, внедрите следующее в методе установки фикстур вашей инфраструктуры тестирования:
AssertionOptions.AssertEquivalencyUsing(options =>
{
options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
options.Using<DateTimeOffset>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTimeOffset>();
return options;
});
Я только что решил это так...
[Test]
public void then_all_items_must_be_set_to_the_current_time()
{
items.Should().OnlyContain(x => DateTime.Now.Subtract(x.Value).Milliseconds <= 100);
}
Но если кто-нибудь знает о способах "Свободных подтверждений", как это делается, пожалуйста, дайте мне знать.