Интеграционное тестирование вызовов с имитацией задержек - PullRequest
1 голос
/ 07 апреля 2020

Я тестирую asp. net Core 2.2 WebApi, который использует EF Core для сохранения данных.

Решение спроектировано с использованием архитектуры CLEAN с шаблоном репозитория / сервиса, создающим каждый компонент индивидуально testable.

Мои интеграционные тесты (с использованием базы данных в памяти XUnit и EF Core) должны проверять следующие случаи:

  1. Пользователь делает запрос и мгновенно делает другой идентичный запрос.
  2. Пользователь делает запрос и через 15 секунд делает другой идентичный запрос.
  3. Пользователь делает запрос и через 30 секунд делает другой идентичный запрос.

Каждый из эти случаи имеют около 5 вариантов каждый. Прямо сейчас я использую вызов Thread.Sleep(x) между каждым из вызовов для имитации этой задержки. Это, конечно, означает, что мои интеграционные тесты занимают возраст . Задержки используются для того, чтобы уровень хранилища сохранял значение DateTime.UtcNow при каждом вызове; значение которого используется сервисным уровнем для выполнения некоторых решений бизнес-логики c.

Мне интересно, есть ли способ «симулировать» эти задержки с использованием инфраструктуры тестирования, устраняя необходимость в том, чтобы тесты действительно ожидали этого времени, и обманывая слой хранилища, используя значение DateTime.UtcNow, которое увеличивается на x.

Спасибо!

1 Ответ

1 голос
/ 07 апреля 2020

Абстрагирование доступа DateTime за некоторым интерфейсом

public interface IDateTime { 
    DateTime UtcNow { get; }

    //...other members as needed. eg: DateTime Now { get; }
} 

, который можно смоделировать, чтобы он вел себя так, как хотелось бы при тестировании.

Производственная реализация будет просто оборачивать фактические DateTime

public class DefaultClock : IDateTime {
    public DateTime UtcNow => DateTime.UtcNow;

    //...
}

и регистрироваться в вашем контейнере DI

service.AddSingleton<IDateTime, DefaultClock>();

При тестировании абстракция может быть смоделирована как необходимо;

//Arrange
DateTime time;
DatTime.TryParse("2009-05-01 12:00:00", out time);

var mock = new Mock<IDateTime>(); //USING MOQ

mock.SetupSequence(_ => _.UtcNow)
    .Returns(time);                 //first call
    .Returns(time.AddSeconds(15))   //second call
    .Returns(time.AddSeconds(30));  //third call

IDateTime clock = mock.Object;

//...inject clock into subject under test
...