diff --git a/Directory.Packages.props b/Directory.Packages.props index 553b7840..34c67cd8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -38,7 +38,6 @@ - @@ -47,7 +46,6 @@ - diff --git a/tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/MySqlEntityTableRepository_Tests.cs b/tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/MySqlEntityTableRepository_Tests.cs deleted file mode 100644 index e9df8a0d..00000000 --- a/tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/MySqlEntityTableRepository_Tests.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using CommunityToolkit.Datasync.TestCommon; -using CommunityToolkit.Datasync.TestCommon.Databases; -using CommunityToolkit.Datasync.TestCommon.Fixtures; -using Microsoft.EntityFrameworkCore; -using Xunit.Abstractions; - -#pragma warning disable CS9113 // Parameter is unread. - -namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test; - -[ExcludeFromCodeCoverage] -[Collection("LiveTestsCollection")] -public class MysqlEntityTableRepository_Tests(MySqlDatabaseFixture fixture, ITestOutputHelper output) : RepositoryTests, IClassFixture, IAsyncLifetime -{ - #region Setup - private readonly Random random = new(); - private List movies = []; - - public async Task InitializeAsync() - { - Context = await MysqlDbContext.CreateContextAsync(fixture.ConnectionString, output); - this.movies = await Context.Movies.AsNoTracking().ToListAsync(); - } - - public async Task DisposeAsync() - { - if (Context is not null) - { - await Context.DisposeAsync(); - } - } - - private MysqlDbContext Context { get; set; } - - protected override bool CanRunLiveTests() => true; - - protected override async Task GetEntityAsync(string id) - => await Context.Movies.AsNoTracking().SingleOrDefaultAsync(m => m.Id == id); - - protected override async Task GetEntityCountAsync() - => await Context.Movies.CountAsync(); - - protected override Task> GetPopulatedRepositoryAsync() - => Task.FromResult>(new EntityTableRepository(Context)); - - protected override Task GetRandomEntityIdAsync(bool exists) - => Task.FromResult(exists ? this.movies[this.random.Next(this.movies.Count)].Id : Guid.NewGuid().ToString()); - #endregion - - [SkippableFact] - public void EntityTableRepository_BadDbSet_Throws() - { - Skip.IfNot(CanRunLiveTests()); - Action act = () => _ = new EntityTableRepository(Context); - act.Should().Throw(); - } - - [SkippableFact] - public void EntityTableRepository_GoodDbSet_Works() - { - Skip.IfNot(CanRunLiveTests()); - Action act = () => _ = new EntityTableRepository(Context); - act.Should().NotThrow(); - } - - [SkippableFact] - public async Task WrapExceptionAsync_ThrowsConflictException_WhenDbConcurrencyUpdateExceptionThrown() - { - Skip.IfNot(CanRunLiveTests()); - EntityTableRepository repository = await GetPopulatedRepositoryAsync() as EntityTableRepository; - string id = await GetRandomEntityIdAsync(true); - MysqlEntityMovie expectedPayload = await GetEntityAsync(id); - - static Task innerAction() => throw new DbUpdateConcurrencyException("Concurrency exception"); - - Func act = async () => await repository.WrapExceptionAsync(id, innerAction); - (await act.Should().ThrowAsync()).WithStatusCode(409).And.WithPayload(expectedPayload); - } - - [SkippableFact] - public async Task WrapExceptionAsync_ThrowsRepositoryException_WhenDbUpdateExceptionThrown() - { - Skip.IfNot(CanRunLiveTests()); - EntityTableRepository repository = await GetPopulatedRepositoryAsync() as EntityTableRepository; - string id = await GetRandomEntityIdAsync(true); - MysqlEntityMovie expectedPayload = await GetEntityAsync(id); - - static Task innerAction() => throw new DbUpdateException("Non-concurrency exception"); - - Func act = async () => await repository.WrapExceptionAsync(id, innerAction); - await act.Should().ThrowAsync(); - } -} diff --git a/tests/CommunityToolkit.Datasync.Server.Test/Live/MySQL_Controller_Tests.cs b/tests/CommunityToolkit.Datasync.Server.Test/Live/MySQL_Controller_Tests.cs deleted file mode 100644 index 4d6dcc0e..00000000 --- a/tests/CommunityToolkit.Datasync.Server.Test/Live/MySQL_Controller_Tests.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using CommunityToolkit.Datasync.Server.EntityFrameworkCore; -using CommunityToolkit.Datasync.Server.Test.Helpers; -using CommunityToolkit.Datasync.TestCommon.Databases; -using CommunityToolkit.Datasync.TestCommon.Fixtures; -using Microsoft.EntityFrameworkCore; -using Microsoft.VisualStudio.TestPlatform.Utilities; -using Xunit.Abstractions; - -namespace CommunityToolkit.Datasync.Server.Test.Live; - -[ExcludeFromCodeCoverage] -[Collection("LiveTestsCollection")] -public class MySQL_Controller_Tests(MySqlDatabaseFixture fixture, ITestOutputHelper output) : LiveControllerTests, IClassFixture, IAsyncLifetime -{ - #region Setup - private readonly Random random = new(); - private List movies = []; - - public async Task InitializeAsync() - { - Context = await MysqlDbContext.CreateContextAsync(fixture.ConnectionString, output); - this.movies = await Context.Movies.AsNoTracking().ToListAsync(); - } - - public async Task DisposeAsync() - { - if (Context is not null) - { - await Context.DisposeAsync(); - } - } - - private MysqlDbContext Context { get; set; } - - protected override string DriverName { get; } = "MySQL"; - - protected override bool CanRunLiveTests() => true; - - protected override async Task GetEntityAsync(string id) - => await Context.Movies.AsNoTracking().SingleOrDefaultAsync(m => m.Id == id); - - protected override async Task GetEntityCountAsync() - => await Context.Movies.CountAsync(); - - protected override Task> GetPopulatedRepositoryAsync() - => Task.FromResult>(new EntityTableRepository(Context)); - - protected override Task GetRandomEntityIdAsync(bool exists) - => Task.FromResult(exists ? this.movies[this.random.Next(this.movies.Count)].Id : Guid.NewGuid().ToString()); - #endregion -} diff --git a/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj b/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj index cf2bdbcf..6e743b60 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj +++ b/tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj @@ -19,10 +19,8 @@ - - diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlDbContext.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlDbContext.cs deleted file mode 100644 index df951d29..00000000 --- a/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlDbContext.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.EntityFrameworkCore; -using Xunit.Abstractions; - -namespace CommunityToolkit.Datasync.TestCommon.Databases; - -[ExcludeFromCodeCoverage] -public class MysqlDbContext(DbContextOptions options) : BaseDbContext(options) -{ - public static async Task CreateContextAsync(string connectionString, ITestOutputHelper output = null, bool clearEntities = true) - { - if (string.IsNullOrEmpty(connectionString)) - { - throw new ArgumentNullException(nameof(connectionString)); - } - - DbContextOptionsBuilder optionsBuilder = new DbContextOptionsBuilder() - .UseMySql(connectionString: connectionString, serverVersion: ServerVersion.AutoDetect(connectionString), options => options.EnableRetryOnFailure()) - .EnableLogging(output); - MysqlDbContext context = new(optionsBuilder.Options); - - await context.InitializeDatabaseAsync(clearEntities); - await context.PopulateDatabaseAsync(); - return context; - } - - internal async Task InitializeDatabaseAsync(bool clearEntities) - { - await Database.EnsureCreatedAsync(); - - if (clearEntities) - { - await ExecuteRawSqlOnEachEntityAsync("DELETE FROM {0}"); - } - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity().Property(m => m.UpdatedAt) - .ValueGeneratedOnAddOrUpdate(); - - modelBuilder.Entity().Property(m => m.Version) - .IsRowVersion(); - - base.OnModelCreating(modelBuilder); - } -} diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlEntityMovie.cs b/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlEntityMovie.cs deleted file mode 100644 index 644ef26f..00000000 --- a/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlEntityMovie.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using CommunityToolkit.Datasync.Server.EntityFrameworkCore; -using CommunityToolkit.Datasync.TestCommon.Models; -using System.ComponentModel.DataAnnotations; - -namespace CommunityToolkit.Datasync.TestCommon.Databases; - -[ExcludeFromCodeCoverage] -public class MysqlEntityMovie : EntityTableData, IMovie, IEquatable -{ - /// - /// True if the movie won the oscar for Best Picture - /// - public bool BestPictureWinner { get; set; } - - /// - /// The running time of the movie - /// - [Required] - [Range(60, 360)] - public int Duration { get; set; } - - /// - /// The MPAA rating for the movie, if available. - /// - public MovieRating Rating { get; set; } = MovieRating.Unrated; - - /// - /// The release date of the movie. - /// - [Required] - public DateOnly ReleaseDate { get; set; } - - /// - /// The title of the movie. - /// - [Required] - [StringLength(128, MinimumLength = 2)] - public string Title { get; set; } = string.Empty; - - /// - /// The year that the movie was released. - /// - [Required] - [Range(1920, 2030)] - public int Year { get; set; } - - /// - /// Determines if this movie has the same content as another movie. - /// - /// The other movie - /// true if the content is the same - public bool Equals(IMovie other) - => other != null - && other.BestPictureWinner == BestPictureWinner - && other.Duration == Duration - && other.Rating == Rating - && other.ReleaseDate == ReleaseDate - && other.Title == Title - && other.Year == Year; -} diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlDatabaseFixture.cs b/tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlDatabaseFixture.cs deleted file mode 100644 index faaaf8c3..00000000 --- a/tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlDatabaseFixture.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Testcontainers.MySql; -using Xunit; - -namespace CommunityToolkit.Datasync.TestCommon.Fixtures; - -/// -/// A test fixture for impementing a MySQL database using Testcontainers. -/// -[ExcludeFromCodeCoverage] -public class MySqlDatabaseFixture : IAsyncLifetime -{ - private readonly MySqlContainer _container; - - public MySqlDatabaseFixture() - { - this._container = new MySqlBuilder() - .WithImage("mysql:lts-oracle") - .WithCleanUp(true) - .WithUsername("testuser") - .WithPassword("testpassword") - .WithDatabase("testdb") - .Build(); - } - - /// - public async Task DisposeAsync() - { - if (this._container is not null) - { - await this._container.DisposeAsync(); - } - } - - /// - public async Task InitializeAsync() - { - await this._container.StartAsync(); - ConnectionString = this._container.GetConnectionString(); - } - - /// - /// The connection string for the MySQL database. - /// - public string ConnectionString { get; private set; } = string.Empty; -} diff --git a/tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlTestFixture.cs b/tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlTestFixture.cs deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/CommunityToolkit.Datasync.TestCommon/RepositoryTests.cs b/tests/CommunityToolkit.Datasync.TestCommon/RepositoryTests.cs index d96b0160..fbe3f4f2 100644 --- a/tests/CommunityToolkit.Datasync.TestCommon/RepositoryTests.cs +++ b/tests/CommunityToolkit.Datasync.TestCommon/RepositoryTests.cs @@ -148,6 +148,10 @@ public async Task CreateAsync_CreatesNewEntity_WithSpecifiedId() TEntity addition = TestData.Movies.OfType(TestData.Movies.BlackPanther, id); TEntity sut = addition.Clone(); await Repository.CreateAsync(sut); + + // Let's sleep for a tiny bit of time to allow any writes to actually happen. + await Task.Delay(100); + TEntity actual = await GetEntityAsync(id); actual.Should().BeEquivalentTo(addition); @@ -169,6 +173,10 @@ public async Task CreateAsync_CreatesNewEntity_WithNullId(string id) addition.Id = id; TEntity sut = addition.Clone(); await Repository.CreateAsync(sut); + + // Let's sleep for a tiny bit of time to allow any writes to actually happen. + await Task.Delay(100); + TEntity actual = await GetEntityAsync(sut.Id); actual.Should().BeEquivalentTo(addition); @@ -205,6 +213,10 @@ public async Task CreateAsync_UpdatesMetadata() byte[] expectedVersion = new byte[] { 0x01, 0x02, 0x03, 0x04 }; sut.Version = expectedVersion.ToArray(); await Repository.CreateAsync(sut); + + // Let's sleep for a tiny bit of time to allow any writes to actually happen. + await Task.Delay(100); + TEntity actual = await GetEntityAsync(id); actual.Should().BeEquivalentTo(addition); @@ -399,6 +411,10 @@ public async Task ReplaceAsync_Replaces_OnVersionMatch() TEntity expected = await GetEntityAsync(id); byte[] version = expected.Version.ToArray(); await Repository.ReplaceAsync(replacement, version); + + // Let's sleep for a tiny bit of time to allow any writes to actually happen. + await Task.Delay(100); + TEntity actual = await GetEntityAsync(id); actual.Should().BeEquivalentTo(replacement).And.NotBeEquivalentTo(expected); @@ -417,6 +433,10 @@ public async Task ReplaceAsync_Replaces_OnNoVersion() TEntity expected = await GetEntityAsync(id); byte[] version = expected.Version.ToArray(); await Repository.ReplaceAsync(replacement); + + // Let's sleep for a tiny bit of time to allow any writes to actually happen. + await Task.Delay(100); + TEntity actual = await GetEntityAsync(id); actual.Should().BeEquivalentTo(replacement).And.NotBeEquivalentTo(expected); diff --git a/tests/CommunityToolkit.Datasync.TestService/CommunityToolkit.Datasync.TestService.csproj b/tests/CommunityToolkit.Datasync.TestService/CommunityToolkit.Datasync.TestService.csproj index 58763ee4..063cb23e 100644 --- a/tests/CommunityToolkit.Datasync.TestService/CommunityToolkit.Datasync.TestService.csproj +++ b/tests/CommunityToolkit.Datasync.TestService/CommunityToolkit.Datasync.TestService.csproj @@ -18,6 +18,5 @@ -