using ChatBot.Data; using ChatBot.Services; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; namespace ChatBot.Tests.Services; public class DatabaseInitializationServiceTests : UnitTestBase { [Fact] public void DatabaseInitializationService_ShouldCreateInstance() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); // Act var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Assert Assert.NotNull(service); } [Fact] public async Task DatabaseInitializationService_StopAsync_ShouldComplete() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert await service.StopAsync(CancellationToken.None); // If we reach here, the method completed successfully Assert.True(true); } [Fact] public async Task StartAsync_ShouldLogCorrectInformation_WhenStopping() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act await service.StopAsync(CancellationToken.None); // Assert loggerMock.Verify( x => x.Log( LogLevel.Information, It.IsAny(), It.Is( (v, t) => v.ToString()!.Contains("Database initialization service stopped") ), It.IsAny(), It.IsAny>() ), Times.Once ); } [Fact] public async Task StartAsync_ShouldHandleCancellationToken() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); var cts = new CancellationTokenSource(); cts.Cancel(); // Cancel immediately // Setup service provider to throw when CreateScope is called serviceProviderMock .Setup(x => x.GetService(typeof(IServiceScopeFactory))) .Returns((IServiceScopeFactory)null!); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert var act = async () => await service.StartAsync(cts.Token); await act.Should().ThrowAsync(); } [Fact] public async Task StartAsync_ShouldLogStartingMessage() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); // Setup service provider to throw when CreateScope is called serviceProviderMock .Setup(x => x.GetService(typeof(IServiceScopeFactory))) .Returns((IServiceScopeFactory)null!); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert var act = async () => await service.StartAsync(CancellationToken.None); await act.Should().ThrowAsync(); loggerMock.Verify( x => x.Log( LogLevel.Information, It.IsAny(), It.Is( (v, t) => v.ToString()!.Contains("Starting database initialization...") ), It.IsAny(), It.IsAny>() ), Times.Once ); } [Fact] public async Task StartAsync_ShouldThrowExceptionWhenServiceProviderFails() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); // Setup service provider to throw when CreateScope is called serviceProviderMock .Setup(x => x.GetService(typeof(IServiceScopeFactory))) .Returns((IServiceScopeFactory)null!); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert var act = async () => await service.StartAsync(CancellationToken.None); await act.Should().ThrowAsync(); // Verify that starting message was logged loggerMock.Verify( x => x.Log( LogLevel.Information, It.IsAny(), It.Is( (v, t) => v.ToString()!.Contains("Starting database initialization...") ), It.IsAny(), It.IsAny>() ), Times.Once ); } [Fact] public async Task StartAsync_ShouldHandleOperationCanceledException() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); var cts = new CancellationTokenSource(); cts.Cancel(); // Cancel immediately // Setup service provider to throw when CreateScope is called serviceProviderMock .Setup(x => x.GetService(typeof(IServiceScopeFactory))) .Returns((IServiceScopeFactory)null!); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert var act = async () => await service.StartAsync(cts.Token); await act.Should().ThrowAsync(); } [Fact] public async Task StartAsync_ShouldHandleGeneralException() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); // Setup service provider to throw when CreateScope is called serviceProviderMock .Setup(x => x.GetService(typeof(IServiceScopeFactory))) .Returns((IServiceScopeFactory)null!); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert var act = async () => await service.StartAsync(CancellationToken.None); await act.Should().ThrowAsync(); } [Fact] public async Task StartAsync_ShouldThrowExceptionWithServiceProviderError() { // Arrange var serviceProviderMock = new Mock(); var loggerMock = new Mock>(); // Setup service provider to throw when CreateScope is called serviceProviderMock .Setup(x => x.GetService(typeof(IServiceScopeFactory))) .Returns((IServiceScopeFactory)null!); var service = new DatabaseInitializationService( serviceProviderMock.Object, loggerMock.Object ); // Act & Assert var act = async () => await service.StartAsync(CancellationToken.None); await act.Should().ThrowAsync(); // Verify that starting message was logged loggerMock.Verify( x => x.Log( LogLevel.Information, It.IsAny(), It.Is( (v, t) => v.ToString()!.Contains("Starting database initialization...") ), It.IsAny(), It.IsAny>() ), Times.Once ); } }