Что является хорошей практикой для написания модульного теста на .net core Ihostedservice?

У меня есть фоновая задача, инициированная при запуске .net core 2.0, наследуемая от backgroundservice, реализующая StartAsync, StopAsync и ExecuteAsync. Эта задача заключается в периодическом обновлении некоторых данных в таблице базы данных на основе некоторой бизнес-логики.

Хотя я могу запускать фоновую задачу как приложение и тестировать с помощью журналов, проверки базы данных и с помощью других инструментов, может ли модульное тестирование необходимо для тестирования фоновой задачи? Если да, то как зарегистрировать задачу как службу с зависимостями и запустить методы запуска и остановки, чтобы подтвердить фактическое и ожидаемое? Оцените базовый пример метода модульного тестирования при тестировании фоновой задачи .net core ihostedservice на основе таймера.

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

  [Fact]
        public async void Run_background_task_success()
        {
            //Arrange
            IServiceCollection services = new ServiceCollection();

            services.AddHostedService<BackgroundManagerTask>();

            var serviceProvider = services.BuildServiceProvider();

            var service = serviceProvider.GetService<IHostedService>() as BackgroundManagerTask;

            var isExecuted = false;
            if(await service.StartAsync(CancellationToken.None))
{
isExecuted = true;
}

            await Task.Delay(10000);
            Assert.True(isExecuted);

            await service.StopAsync(CancellationToken.None);
        }



Ответы (1)


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

[Fact]
public void BackgroundManagerUpdatingDataTest()
{
    // Arrange
    Mock<IDataAccess> dbMock = new Mock<IDataAccess>();
    dbMock.Setup(x => x.UpdateSomethingInDB(It.IsAny<BusinessObject>())).Returns(1); // One row updated from the DML in UpdateSomethingInDB from the BusinessObject
    
    BackgroundManager sut = new BackgroundManager(dbMock.Object); // System under test.

    // Act
    await sut.StartAsync(CancellationToken.None);
    await Task.Delay(500); // Give the test some time to execute.
    await sut.StopAsync(CancellationToken.None); // Stop the Background Service.

    // Assert
    dbMock.Verify(x => x.UpdateSomethingInDB(It.IsAny<BusinessObject>()), Times.Exactly(1));
}

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

Конечно, вы можете смоделировать любую другую зависимость, используя Moq, и утверждать все, что захотите. проверять.

person Jimenemex    schedule 10.02.2021