Как я могу написать модульный тест для моей фоновой службы? - PullRequest
0 голосов
/ 18 июня 2019

Я работаю с HostBuilder в .NET Core (не WebHost!).

В моем приложении запущена одна размещенная служба, которая переопределяет метод ExecuteAsync / StopAsync фоновой службы, и я хочудля его модульного тестирования.

Вот мой HostedService:

    public class DeviceToCloudMessageHostedService : BackgroundService
    {
        private readonly IDeviceToCloudMessageService _deviceToCloudMessageService;
        private readonly AppConfig _appConfig;

        public DeviceToCloudMessageHostedService(IDeviceToCloudMessageService deviceToCloudMessageService, IOptionsMonitor<AppConfig> appConfig)
        {
            _deviceToCloudMessageService = deviceToCloudMessageService;
            _appConfig = appConfig.CurrentValue;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                await _deviceToCloudMessageService.DoStuff(stoppingToken);
                await Task.Delay(_appConfig.Parameter1, stoppingToken);
            }
        }

        public override Task StopAsync(CancellationToken cancellationToken)
        {
            Log.Information("Task Cancelled");
            _deviceToCloudMessageService.EndStuff();
            return base.StopAsync(cancellationToken);
        }

Я уже нашел этот пост Интеграционный тест для размещенного сервиса .Net-Core` Но это объясняется дляQueuedBackgroundService, и я действительно не знаю, смогу ли я проверить мой таким же образом.

Я просто хочу знать, выполняется ли мой код.Я не хочу никакого конкретного результата.Ты хоть представляешь, как я могу это проверить?Большое спасибо.

1 Ответ

0 голосов
/ 18 июня 2019

Вы по-прежнему сможете использовать формат, аналогичный связанному ответу.

Смоделируйте зависимости и внедрите их, вызовите тестируемые методы и подтвердите ожидаемое поведение.

Следующее использует Moq для макетирования зависимостей вместе с ServiceCollection для выполнения тяжелой работы по внедрению зависимостей.

[TestMethod]
public async Task DeviceToCloudMessageHostedService_Should_DoStuff() {
    //Arrange
    IServiceCollection services = new ServiceCollection();
    services.AddSingleton<IHostedService, DeviceToCloudMessageHostedService>();
    //mock the dependencies for injection
    services.AddSingleton(Mock.Of<IDeviceToCloudMessageService>(_ =>
        _.DoStuff(It.IsAny<CancellationToken>()) == Task.CompletedTask
    ));
    services.AddSingleton(Mock.Of<IOptionsMonitor<AppConfig>>(_ =>
        _.CurrentValue == Mock.Of<AppConfig>(c => 
            c.Parameter1 == TimeSpan.FromMilliseconds(1000)
        )
    ));
    var serviceProvider = services.BuildServiceProvider();
    var hostedService = serviceProvider.GetService<IHostedService>();

    //Act
    await hostedService.StartAsync(CancellationToken.None);
    await Task.Delay(1000);//Give some time to invoke the methods under test
    await hostedService.StopAsync(CancellationToken.None);

    //Assert
    var deviceToCloudMessageService = serviceProvider
        .GetRequiredService<IDeviceToCloudMessageService>();
    //extracting mock to do verifications
    var mock = Mock.Get(deviceToCloudMessageService);
    //assert expected behavior
    mock.Verify(_ => _.DoStuff(It.IsAny<CancellationToken>()), Times.AtLeastOnce);
    mock.Verify(_ => _.EndStuff(), Times.AtLeastOnce());
}

Теперь, в идеале, это будет учитываться как тестирование кода инфраструктуры, так как вы в основном проверяете, что BackgroundService ведет себя так, как ожидалось при запуске, но это должно продемонстрировать достаточно о том, как можно протестировать такой сервис в изоляции

...