From 903e59c8cc13506641fe0055c09eca672c7acda0 Mon Sep 17 00:00:00 2001 From: Wouter Van Ranst Date: Tue, 27 Aug 2024 06:33:39 +0200 Subject: [PATCH] UNIT TEST TRYOUTS --- .../Arius.Core.Domain.csproj | 1 + src/Arius.Core.Domain/AriusConfiguration.cs | 10 +- .../DirectoryInfoExtensions.cs | 16 +- .../Arius.Core.Infrastructure.csproj | 1 + .../Repositories/StateDbRepositoryFactory.cs | 13 +- .../Arius.Core.New.UnitTests.csproj | 1 + .../Fixtures/AriusFixture - Copy.cs | 262 ++++++++++++++++ .../Fixtures/AriusFixture.cs | 3 - ...iteStateDbRepositoryFactoryTests - Copy.cs | 280 ++++++++++++++++++ 9 files changed, 569 insertions(+), 18 deletions(-) create mode 100644 src/Arius.Core.New.UnitTests/Fixtures/AriusFixture - Copy.cs create mode 100644 src/Arius.Core.New.UnitTests/SqliteStateDbRepositoryFactoryTests - Copy.cs diff --git a/src/Arius.Core.Domain/Arius.Core.Domain.csproj b/src/Arius.Core.Domain/Arius.Core.Domain.csproj index 5be4df4e..e6f893e3 100644 --- a/src/Arius.Core.Domain/Arius.Core.Domain.csproj +++ b/src/Arius.Core.Domain/Arius.Core.Domain.csproj @@ -8,6 +8,7 @@ + diff --git a/src/Arius.Core.Domain/AriusConfiguration.cs b/src/Arius.Core.Domain/AriusConfiguration.cs index 6073d6cc..8d2fe16c 100644 --- a/src/Arius.Core.Domain/AriusConfiguration.cs +++ b/src/Arius.Core.Domain/AriusConfiguration.cs @@ -1,10 +1,12 @@ -namespace Arius.Core.Domain; +using System.IO.Abstractions; + +namespace Arius.Core.Domain; public record AriusConfiguration { - public required DirectoryInfo LocalConfigRoot { get; set; } + public required IDirectoryInfo LocalConfigRoot { get; set; } - private DirectoryInfo StateDbRoot => LocalConfigRoot.CreateSubdirectory("StateDbs"); - public DirectoryInfo GetLocalStateDbFolderForRepositoryName(string containerName) => StateDbRoot.CreateSubdirectory(containerName); + private IDirectoryInfo StateDbRoot => LocalConfigRoot.CreateSubdirectory("StateDbs"); + public IDirectoryInfo GetLocalStateDbFolderForRepositoryName(string containerName) => StateDbRoot.CreateSubdirectory(containerName); } \ No newline at end of file diff --git a/src/Arius.Core.Domain/DirectoryInfoExtensions.cs b/src/Arius.Core.Domain/DirectoryInfoExtensions.cs index a5380cfd..358518e0 100644 --- a/src/Arius.Core.Domain/DirectoryInfoExtensions.cs +++ b/src/Arius.Core.Domain/DirectoryInfoExtensions.cs @@ -1,9 +1,9 @@ -namespace WouterVanRanst.Utils; +//namespace WouterVanRanst.Utils; -public static class DirectoryInfoExtensions -{ - public static string GetFullName(this DirectoryInfo directoryInfo, string fileName) - { - return Path.Combine(directoryInfo.FullName, fileName); - } -} \ No newline at end of file +//public static class DirectoryInfoExtensions +//{ +// public static string GetFullName(this DirectoryInfo directoryInfo, string fileName) +// { +// return Path.Combine(directoryInfo.FullName, fileName); +// } +//} \ No newline at end of file diff --git a/src/Arius.Core.Infrastructure/Arius.Core.Infrastructure.csproj b/src/Arius.Core.Infrastructure/Arius.Core.Infrastructure.csproj index 208023bf..c3fde73c 100644 --- a/src/Arius.Core.Infrastructure/Arius.Core.Infrastructure.csproj +++ b/src/Arius.Core.Infrastructure/Arius.Core.Infrastructure.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Arius.Core.Infrastructure/Repositories/StateDbRepositoryFactory.cs b/src/Arius.Core.Infrastructure/Repositories/StateDbRepositoryFactory.cs index 358a6f57..af362533 100644 --- a/src/Arius.Core.Infrastructure/Repositories/StateDbRepositoryFactory.cs +++ b/src/Arius.Core.Infrastructure/Repositories/StateDbRepositoryFactory.cs @@ -1,4 +1,5 @@ -using Arius.Core.Domain; +using System.IO.Abstractions; +using Arius.Core.Domain; using Arius.Core.Domain.Repositories; using Arius.Core.Domain.Storage; using Azure; @@ -10,16 +11,22 @@ namespace Arius.Core.Infrastructure.Repositories; public class SqliteStateDbRepositoryFactory : IStateDbRepositoryFactory { private readonly IStorageAccountFactory storageAccountFactory; + private readonly IFileSystem fileSystem; private readonly AriusConfiguration config; private readonly ILogger logger; public SqliteStateDbRepositoryFactory( IStorageAccountFactory storageAccountFactory, IOptions config, + IFileSystem fileSystem, ILogger logger) + + + { this.storageAccountFactory = storageAccountFactory; + this.fileSystem = fileSystem; this.config = config.Value; this.logger = logger; } @@ -52,9 +59,9 @@ public async Task CreateAsync(RepositoryOptions repositoryOp private async Task GetLocalRepositoryFullNameAsync(IRepository repository, DirectoryInfo stateDbFolder, RepositoryVersion version, string passphrase) { - var localPath = stateDbFolder.GetFullName(version.GetFileSystemName()); + var localPath = fileSystem.Path.Combine(stateDbFolder.FullName, version.GetFileSystemName()); - if (File.Exists(localPath)) + if (fileSystem.File.Exists(localPath)) return localPath; try diff --git a/src/Arius.Core.New.UnitTests/Arius.Core.New.UnitTests.csproj b/src/Arius.Core.New.UnitTests/Arius.Core.New.UnitTests.csproj index 8e9c06bf..3c6141dc 100644 --- a/src/Arius.Core.New.UnitTests/Arius.Core.New.UnitTests.csproj +++ b/src/Arius.Core.New.UnitTests/Arius.Core.New.UnitTests.csproj @@ -24,6 +24,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture - Copy.cs b/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture - Copy.cs new file mode 100644 index 00000000..a76f55cc --- /dev/null +++ b/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture - Copy.cs @@ -0,0 +1,262 @@ +using System.IO.Abstractions; +using Arius.Core.Domain; +using Arius.Core.Domain.Repositories; +using Arius.Core.Domain.Services; +using Arius.Core.Domain.Storage; +using Arius.Core.Infrastructure.Repositories; +using Arius.Core.New.UnitTests.Fakes; +using MediatR; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using NSubstitute; + +namespace Arius.Core.New.UnitTests.Fixtures; + +public class AriusFixture2 +{ + public AriusFixture2() + { + //Setup the configuration + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddUserSecrets(optional: true) + .Build(); + + //UnitTestRoot = new DirectoryInfo(Path.Combine(@"C:\AriusTest", $"UnitTests-{DateTime.Now:yyMMddHHmmss}-{Random.Shared.Next()}")); + //UnitTestRoot.Create(); + + // Setup the service collection + var services = new ServiceCollection(); + + // Add configuration to the service collection + testRepositoryOptions = configuration.GetSection("RepositoryOptions").Get()!; + + // Register the actual services + services.AddArius(c => c.LocalConfigRoot = FileSystem.DirectoryInfo.New("bla")); + services.AddLogging(); + + // Add additional services + ConfigureServices(services, ServiceConfiguration.Mocked); + + // Build the service provider + var serviceProvider = services.BuildServiceProvider(); + + // Get the required services + StorageAccountFactory = serviceProvider.GetRequiredService(); + Mediator = serviceProvider.GetRequiredService(); + + //StorageAccountFactory = Substitute.For(); + //FileSystem = Substitute.For(); + //Config = Substitute.For(); + + //var options = Substitute.For>(); + //options.Value.Returns(Config); + + Factory = new SqliteStateDbRepositoryFactory(StorageAccountFactory, options, FileSystem, NullLogger.Instance); + + } + + private void ConfigureServices(IServiceCollection services, ServiceConfiguration serviceConfiguration) + { + services.AddSingleton(Substitute.For()); + services.AddSingleton(); + } + + public SqliteStateDbRepositoryFactory Factory { get; } + public IStorageAccountFactory StorageAccountFactory { get; } + public IFileSystem FileSystem { get; } + public IMediator Mediator { get; } + //public AriusConfiguration Config { get; } + + public IRepository repository; + public string localPath; + public TestRepositoryOptions testRepositoryOptions; + public RepositoryOptions repositoryOptions; + public RepositoryVersion? version; + public IBlob blob; +} + +public static class FixtureExtensions +{ + public static AriusFixture2 GivenRepositoryWithNoVersions(this AriusFixture2 fixture) + { + fixture.repository.GetRepositoryVersions().Returns(AsyncEnumerable.Empty()); + return fixture; + } +} + +public class SqliteStateDbRepositoryFactoryTests3 +{ + private readonly AriusFixture2 fixture; + + public SqliteStateDbRepositoryFactoryTests3() + { + fixture = new AriusFixture2(); + } + + [Fact] + public async Task CreateAsync_WhenNoVersionsAvailable_ShouldReturnNewFileName() + { + // Arrange + fixture.GivenRepositoryWithNoVersions(); + + // Act + var result = await fixture.Factory.CreateAsync(fixture.repositoryOptions); + + } +} + + + +//public abstract class AriusFixture : IDisposable +//{ +// public Lazy mockedTestRepositoryOptions; +// public Lazy realTestRepositoryOptions; + +// private Lazy mockedMediator; +// private Lazy mockedStorageAccountFactory; + +// private Lazy realMediator; +// private Lazy realStorageAccountFactory; + +// private Lazy mockedServiceProvider; +// private Lazy realServiceProvider; + +// public DirectoryInfo UnitTestRoot { get; } + + +// protected AriusFixture() +// { +// // Setup the configuration +// var configuration = new ConfigurationBuilder() +// .SetBasePath(Directory.GetCurrentDirectory()) +// .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) +// .AddUserSecrets(optional: true) +// .Build(); + +// UnitTestRoot = new DirectoryInfo(Path.Combine(@"C:\AriusTest", $"UnitTests-{DateTime.Now:yyMMddHHmmss}-{Random.Shared.Next()}")); +// UnitTestRoot.Create(); + +// InitializeMockedServices(); +// InitializeRealServices(); + + +// void InitializeMockedServices() +// { +// // Setup the service collection +// var services = new ServiceCollection(); + +// // Add configuration to the service collection +// mockedTestRepositoryOptions = new Lazy(configuration.GetSection("RepositoryOptions").Get()!); + +// // Register the actual services +// services.AddArius(c => c.LocalConfigRoot = UnitTestRoot); +// services.AddLogging(); + +// // Add additional services +// ConfigureServices(services, ServiceConfiguration.Mocked); + +// // Build the service provider +// mockedServiceProvider = new Lazy(services.BuildServiceProvider()); + +// // Get the required services +// mockedStorageAccountFactory = new Lazy(mockedServiceProvider.Value.GetRequiredService()); +// mockedMediator = new Lazy(mockedServiceProvider.Value.GetRequiredService()); +// } + +// void InitializeRealServices() +// { +// // Setup the service collection +// var services = new ServiceCollection(); + +// // Add configuration to the service collection +// realTestRepositoryOptions = new Lazy(configuration.GetSection("RepositoryOptions").Get()!); + +// // Register the actual services +// services.AddArius(c => c.LocalConfigRoot = UnitTestRoot); +// services.AddLogging(); + +// // Add additional services +// ConfigureServices(services, ServiceConfiguration.Real); + +// // Build the service provider +// realServiceProvider = new Lazy(services.BuildServiceProvider()); + +// // Get the required services +// realStorageAccountFactory = new Lazy(realServiceProvider.Value.GetRequiredService()); +// realMediator = new Lazy(realServiceProvider.Value.GetRequiredService()); +// } +// } + +// public IStorageAccountFactory GetStorageAccountFactory(ServiceConfiguration serviceConfiguration) => +// serviceConfiguration == ServiceConfiguration.Mocked ? +// mockedStorageAccountFactory.Value : +// realStorageAccountFactory.Value; + +// public IMediator GetMediator(ServiceConfiguration serviceConfiguration) => +// serviceConfiguration == ServiceConfiguration.Mocked ? +// mockedMediator.Value : +// realMediator.Value; + +// public TestRepositoryOptions GetTestRepositoryOptions(ServiceConfiguration serviceConfiguration) => +// serviceConfiguration == ServiceConfiguration.Mocked ? +// mockedTestRepositoryOptions.Value : +// realTestRepositoryOptions.Value; + +// public StorageAccountOptions GetStorageAccountOptions(ServiceConfiguration serviceConfiguration) => +// new() +// { +// AccountName = GetTestRepositoryOptions(serviceConfiguration).AccountName, +// AccountKey = GetTestRepositoryOptions(serviceConfiguration).AccountKey +// }; + +// public RepositoryOptions GetRepositoryOptions(ServiceConfiguration serviceConfiguration) => +// new() +// { +// AccountName = GetTestRepositoryOptions(serviceConfiguration).AccountName, +// AccountKey = GetTestRepositoryOptions(serviceConfiguration).AccountKey, +// ContainerName = GetTestRepositoryOptions(serviceConfiguration).ContainerName, +// Passphrase = GetTestRepositoryOptions(serviceConfiguration).Passphrase +// }; + +// public IStateDbRepositoryFactory GetStateDbRepositoryFactory(ServiceConfiguration serviceConfiguration) => +// serviceConfiguration == ServiceConfiguration.Mocked ? +// mockedServiceProvider.Value.GetRequiredService() : +// realServiceProvider.Value.GetRequiredService(); + +// public AriusConfiguration GetAriusConfiguration(ServiceConfiguration serviceConfiguration) => +// serviceConfiguration == ServiceConfiguration.Mocked ? +// mockedServiceProvider.Value.GetRequiredService>().Value : +// realServiceProvider.Value.GetRequiredService>().Value; + +// protected abstract void ConfigureServices(IServiceCollection services, ServiceConfiguration serviceConfiguration); + +// public void Dispose() +// { +// // Cleanup if necessary +// } +//} + +//public class RequestHandlerFixture : AriusFixture +//{ +// protected override void ConfigureServices(IServiceCollection services, ServiceConfiguration serviceConfiguration) +// { +// if (serviceConfiguration == ServiceConfiguration.Mocked) +// { +// // Substitute for the dependencies + +// services.AddSingleton(Substitute.For()); +// services.AddSingleton(); +// } +// } +//} + +//public enum ServiceConfiguration +//{ +// Mocked, +// Real +//} \ No newline at end of file diff --git a/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture.cs b/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture.cs index d72d37fe..20e1d291 100644 --- a/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture.cs +++ b/src/Arius.Core.New.UnitTests/Fixtures/AriusFixture.cs @@ -2,13 +2,10 @@ using Arius.Core.Domain.Repositories; using Arius.Core.Domain.Services; using Arius.Core.Domain.Storage; -using Arius.Core.Infrastructure.Repositories; -using Arius.Core.New.Services; using Arius.Core.New.UnitTests.Fakes; using MediatR; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NSubstitute; diff --git a/src/Arius.Core.New.UnitTests/SqliteStateDbRepositoryFactoryTests - Copy.cs b/src/Arius.Core.New.UnitTests/SqliteStateDbRepositoryFactoryTests - Copy.cs new file mode 100644 index 00000000..3fa8c4df --- /dev/null +++ b/src/Arius.Core.New.UnitTests/SqliteStateDbRepositoryFactoryTests - Copy.cs @@ -0,0 +1,280 @@ +using Arius.Core.Domain; +using Arius.Core.Domain.Repositories; +using Arius.Core.Domain.Storage; +using Arius.Core.Infrastructure.Repositories; +using Arius.Core.New.UnitTests.Fixtures; +using Azure; +using FluentAssertions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using NSubstitute; +using System.IO.Abstractions.TestingHelpers; + +namespace Arius.Core.New.UnitTests; + +public sealed class SqliteStateDbRepositoryFactoryTests2 : IClassFixture +{ + private readonly RequestHandlerFixture fixture; + private MockFileSystem mockFileSystem; + private IStorageAccountFactory mockStorageAccountFactory; + private SqliteStateDbRepositoryFactory repositoryFactory; + private IStateDbRepository stateDbRepository; + private RepositoryOptions repositoryOptions; + + public SqliteStateDbRepositoryFactoryTests2(RequestHandlerFixture fixture) + { + this.fixture = fixture; + } + + [Theory] + [InlineData(ServiceConfiguration.Mocked)] + [InlineData(ServiceConfiguration.Real)] + public async Task CreateAsync_WhenNoVersionsAvailable_ShouldReturnNewFileName(ServiceConfiguration configuration) + { + // Arrange + GivenAzureRepositoryWithNoVersions(configuration); + GivenLocalFilesystem(configuration); + WhenRepositoryIsCreated(); + + // Act + var result = await repositoryFactory.CreateAsync(repositoryOptions); + + // Assert + ThenNewFileShouldBeCreatedWithCurrentTimestamp(result); + ThenRepositoryVersionShouldBeTheTimestamp(result); + } + + [Theory] + [InlineData(ServiceConfiguration.Mocked)] + [InlineData(ServiceConfiguration.Real)] + public async Task CreateAsync_WhenNoVersionSpecifiedAndLatestVersionNotCached_ShouldDownloadLatestVersion(ServiceConfiguration configuration) + { + // Arrange + GivenAzureRepositoryWithVersions(configuration, "v1.0", "v1.1", "v2.0"); + GivenLocalFilesystem(configuration); + WhenRepositoryIsCreated(); + + // Act + var result = await repositoryFactory.CreateAsync(repositoryOptions); + + // Assert + ThenLatestVersionShouldBeDownloaded(result, "v2.0"); + ThenFileShouldBeCachedLocally(result); + } + + [Theory] + [InlineData(ServiceConfiguration.Mocked)] + [InlineData(ServiceConfiguration.Real)] + public async Task CreateAsync_WhenLatestVersionCached_ShouldReturnCachedRepositoryWithCorrectVersion(ServiceConfiguration configuration) + { + // Arrange + GivenAzureRepositoryWithVersions(configuration, "v1.0", "v1.1", "v2.0"); + GivenLocalFilesystemWithCachedFile(configuration, "v2.0"); + WhenRepositoryIsCreated(); + + // Act + var result = await repositoryFactory.CreateAsync(repositoryOptions); + + // Assert + ThenRepositoryVersionShouldBe(result, "v2.0"); + ThenDownloadAsyncShouldNotBeCalled(configuration); + } + + [Theory] + [InlineData(ServiceConfiguration.Mocked)] + [InlineData(ServiceConfiguration.Real)] + public async Task CreateAsync_WhenSpecificVersionNotCached_ShouldDownloadAndCacheSpecificVersion(ServiceConfiguration configuration) + { + // Arrange + GivenAzureRepositoryWithVersions(configuration, "v1.0", "v1.1", "v2.0"); + GivenLocalFilesystem(configuration); + WhenRepositoryIsCreated(); + + // Act + var requestedVersion = new RepositoryVersion { Name = "v1.1" }; + var result = await repositoryFactory.CreateAsync(repositoryOptions, requestedVersion); + + // Assert + ThenRepositoryVersionShouldBe(result, "v1.1"); + ThenFileShouldBeCachedLocally(result); + ThenDownloadAsyncShouldBeCalled(configuration); + } + + [Theory] + [InlineData(ServiceConfiguration.Mocked)] + [InlineData(ServiceConfiguration.Real)] + public async Task CreateAsync_WhenSpecificVersionCached_ShouldReturnCachedRepositoryWithCorrectVersion(ServiceConfiguration configuration) + { + // Arrange + GivenAzureRepositoryWithVersions(configuration, "v1.0", "v1.1", "v2.0"); + GivenLocalFilesystemWithCachedFile(configuration, "v1.1"); + WhenRepositoryIsCreated(); + + // Act + var requestedVersion = new RepositoryVersion { Name = "v1.1" }; + var result = await repositoryFactory.CreateAsync(repositoryOptions, requestedVersion); + + // Assert + ThenRepositoryVersionShouldBe(result, "v1.1"); + ThenDownloadAsyncShouldNotBeCalled(configuration); + } + + [Theory] + [InlineData(ServiceConfiguration.Mocked)] + [InlineData(ServiceConfiguration.Real)] + public async Task CreateAsync_WhenSpecificVersionDoesNotExist_ShouldThrowArgumentException(ServiceConfiguration configuration) + { + // Arrange + GivenAzureRepositoryWithVersionButNotExist(configuration, "v3.0"); + GivenLocalFilesystem(configuration); + WhenRepositoryIsCreated(); + + // Act + Func act = async () => await repositoryFactory.CreateAsync(repositoryOptions, new RepositoryVersion { Name = "v3.0" }); + + // Assert + await act.Should().ThrowAsync().WithMessage("The requested version was not found*"); + } + + private void GivenAzureRepositoryWithNoVersions(ServiceConfiguration configuration) + { + mockStorageAccountFactory = Substitute.For(); + var repository = Substitute.For(); + repository.GetRepositoryVersions().Returns(AsyncEnumerable.Empty()); + mockStorageAccountFactory.GetRepository(Arg.Any()).Returns(repository); + + SetupFactory(configuration); + } + + private void GivenAzureRepositoryWithVersions(ServiceConfiguration configuration, params string[] versions) + { + mockStorageAccountFactory = Substitute.For(); + var repository = Substitute.For(); + repository.GetRepositoryVersions().Returns(versions.Select(v => new RepositoryVersion { Name = v }).ToAsyncEnumerable()); + mockStorageAccountFactory.GetRepository(Arg.Any()).Returns(repository); + + SetupFactory(configuration); + } + + private void GivenAzureRepositoryWithVersionButNotExist(ServiceConfiguration configuration, string versionName) + { + mockStorageAccountFactory = Substitute.For(); + var repository = Substitute.For(); + var blob = Substitute.For(); + repository.GetRepositoryVersionBlob(Arg.Any()).Returns(blob); + repository.DownloadAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(Task.FromException(new RequestFailedException(404, "Blob not found", "BlobNotFound", null))); + mockStorageAccountFactory.GetRepository(Arg.Any()).Returns(repository); + + SetupFactory(configuration); + } + + private void GivenLocalFilesystem(ServiceConfiguration configuration) + { + mockFileSystem = new MockFileSystem(); + SetupFactory(configuration); + } + + private void GivenLocalFilesystemWithCachedFile(ServiceConfiguration configuration, string versionName) + { + mockFileSystem = new MockFileSystem(); + var cachedFilePath = GetLocalStateDbForRepositoryFullName(configuration, repositoryOptions, new RepositoryVersion { Name = versionName }); + CreateValidSqliteDatabase(cachedFilePath); + SetupFactory(configuration); + } + + private void WhenRepositoryIsCreated() + { + var mockConfig = Substitute.For>(); + mockConfig.Value.Returns(new AriusConfiguration + { + LocalConfigRoot = new DirectoryInfo(@"C:\AriusTest") + // Setup your configuration here + }); + + var mockLogger = Substitute.For>(); + repositoryFactory = new SqliteStateDbRepositoryFactory(mockStorageAccountFactory, mockConfig, mockLogger); + + repositoryOptions = new RepositoryOptions + { + AccountName = "testAccount", + AccountKey = "testKey", + ContainerName = "testContainer", + Passphrase = "testPassphrase" + }; + } + + private void ThenNewFileShouldBeCreatedWithCurrentTimestamp(IStateDbRepository result) + { + var expectedFileName = $"{DateTime.UtcNow:s}".Replace(":", ""); + var files = mockFileSystem.AllFiles; + files.Should().Contain(f => f.Contains(expectedFileName)); + } + + private void ThenRepositoryVersionShouldBeTheTimestamp(IStateDbRepository result) + { + result.Version.Name.Should().Be($"{DateTime.UtcNow:s}".Replace(":", "")); + } + + private void ThenLatestVersionShouldBeDownloaded(IStateDbRepository result, string expectedVersion) + { + result.Version.Name.Should().Be(expectedVersion); + } + + private void ThenFileShouldBeCachedLocally(IStateDbRepository result) + { + var expectedFileName = result.Version.Name.Replace(":", ""); + var files = mockFileSystem.AllFiles; + files.Should().Contain(f => f.Contains(expectedFileName)); + } + + private void ThenRepositoryVersionShouldBe(IStateDbRepository result, string expectedVersion) + { + result.Version.Name.Should().Be(expectedVersion); + } + + private void ThenDownloadAsyncShouldBeCalled(ServiceConfiguration configuration) + { + if (configuration == ServiceConfiguration.Mocked) + { + var repository = mockStorageAccountFactory.GetRepository(repositoryOptions); + repository.Received(1).DownloadAsync(Arg.Any(), Arg.Any(), Arg.Any()); + } + } + + private void ThenDownloadAsyncShouldNotBeCalled(ServiceConfiguration configuration) + { + if (configuration == ServiceConfiguration.Mocked) + { + var repository = mockStorageAccountFactory.GetRepository(repositoryOptions); + repository.DidNotReceive().DownloadAsync(Arg.Any(), Arg.Any(), Arg.Any()); + } + } + + private void SetupFactory(ServiceConfiguration configuration) + { + if (configuration == ServiceConfiguration.Real) + { + // Set up real services here if needed + throw new NotImplementedException(); + } + } + + private string GetLocalStateDbForRepositoryFullName(ServiceConfiguration configuration, RepositoryOptions repositoryOptions, RepositoryVersion version) + { + return fixture.GetAriusConfiguration(configuration) + .GetLocalStateDbFolderForRepositoryName(repositoryOptions.ContainerName) + .GetFullName(version.GetFileSystemName()); + } + + private void CreateValidSqliteDatabase(string filePath) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite($"Data Source={filePath}"); + + using var context = new SqliteStateDbContext(optionsBuilder.Options); + context.Database.EnsureCreated(); + context.Database.Migrate(); + } +} \ No newline at end of file