Skip to content

Commit b59bf2a

Browse files
authored
(#344) TestContainer support for MySql Testing
* (#344) TestContainer for MySQL. * (#344) Added MySqlDatabaseFixture
1 parent 7267e5a commit b59bf2a

File tree

10 files changed

+74
-126
lines changed

10 files changed

+74
-126
lines changed

.github/copilot-instructions.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Datasync Community Toolkit
2+
3+
This is a set of instructions for the GitHub Copilot to support the Datasync Community Toolkit.
4+
5+
## Project Layout
6+
7+
* `/docs` - documentation, mostly Markdown supporting `mkdocs` document generation.
8+
* `/infra` - infrastructure definition to support live testing.
9+
* `/samples` - sample code for the library.
10+
* `/src` - source code for the NuGet packages.
11+
* `/templates` - the template source code.
12+
* `/tests` - the test projects

Directory.Packages.props

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
4141
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
4242
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.4" />
43+
<PackageVersion Include="TestContainers.MySql" Version="4.4.0" />
4344
<PackageVersion Include="xunit" Version="2.9.3" />
4445
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
4546
<PackageVersion Include="coverlet.collector" Version="6.0.4" />

infra/modules/mysql.bicep

-89
This file was deleted.

infra/resources.bicep

-15
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ var appServiceName = 'web-${resourceToken}'
3434
var azsqlServerName = 'sql-${resourceToken}'
3535
var cosmosServerName = 'cosmos-${resourceToken}'
3636
var pgsqlServerName = 'pgsql-${resourceToken}'
37-
var mysqlServerName = 'mysql-${resourceToken}'
3837
var mongoServerName = 'mongo-${resourceToken}'
3938
var mongoaciServerName = 'mongoaci-${resourceToken}'
4039

@@ -81,19 +80,6 @@ module pgsql './modules/postgresql.bicep' = {
8180
}
8281
}
8382

84-
module mysql './modules/mysql.bicep' = {
85-
name: 'mysql-deployment-${resourceToken}'
86-
params: {
87-
location: location
88-
tags: tags
89-
databaseName: testDatabaseName
90-
firewallRules: clientIpFirewallRules
91-
sqlServerName: mysqlServerName
92-
sqlAdminUsername: sqlAdminUsername
93-
sqlAdminPassword: sqlAdminPassword
94-
}
95-
}
96-
9783
module cosmos './modules/cosmos.bicep' = {
9884
name: 'cosmos-deployment-${resourceToken}'
9985
params: {
@@ -150,6 +136,5 @@ output AZSQL_CONNECTIONSTRING string = azuresql.outputs.AZSQL_CONNECTIONSTRING
150136
output COSMOS_CONNECTIONSTRING string = cosmos.outputs.COSMOS_CONNECTIONSTRING
151137
output MONGO_CONNECTIONSTRING string = mongodb.outputs.MONGO_CONNECTIONSTRING
152138
output MONGOACI_CONNECTIONSTRING string = mongoaci.outputs.MONGO_CONNECTIONSTRING
153-
output MYSQL_CONNECTIONSTRING string = mysql.outputs.MYSQL_CONNECTIONSTRING
154139
output PGSQL_CONNECTIONSTRING string = pgsql.outputs.PGSQL_CONNECTIONSTRING
155140
output SERVICE_ENDPOINT string = app_service.outputs.SERVICE_ENDPOINT

tests/CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test/MySqlEntityTableRepository_Tests.cs

+5-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using CommunityToolkit.Datasync.TestCommon;
66
using CommunityToolkit.Datasync.TestCommon.Databases;
7+
using CommunityToolkit.Datasync.TestCommon.Fixtures;
78
using Microsoft.EntityFrameworkCore;
89
using Xunit.Abstractions;
910

@@ -13,19 +14,16 @@ namespace CommunityToolkit.Datasync.Server.EntityFrameworkCore.Test;
1314

1415
[ExcludeFromCodeCoverage]
1516
[Collection("LiveTestsCollection")]
16-
public class MysqlEntityTableRepository_Tests(DatabaseFixture fixture, ITestOutputHelper output) : RepositoryTests<MysqlEntityMovie>, IAsyncLifetime
17+
public class MysqlEntityTableRepository_Tests(MySqlDatabaseFixture fixture, ITestOutputHelper output) : RepositoryTests<MysqlEntityMovie>, IClassFixture<MySqlDatabaseFixture>, IAsyncLifetime
1718
{
1819
#region Setup
1920
private readonly Random random = new();
2021
private List<MysqlEntityMovie> movies = [];
2122

2223
public async Task InitializeAsync()
2324
{
24-
if (!string.IsNullOrEmpty(ConnectionStrings.MySql))
25-
{
26-
Context = await MysqlDbContext.CreateContextAsync(ConnectionStrings.MySql, output);
27-
this.movies = await Context.Movies.AsNoTracking().ToListAsync();
28-
}
25+
Context = await MysqlDbContext.CreateContextAsync(fixture.ConnectionString, output);
26+
this.movies = await Context.Movies.AsNoTracking().ToListAsync();
2927
}
3028

3129
public async Task DisposeAsync()
@@ -38,7 +36,7 @@ public async Task DisposeAsync()
3836

3937
private MysqlDbContext Context { get; set; }
4038

41-
protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(ConnectionStrings.MySql);
39+
protected override bool CanRunLiveTests() => true;
4240

4341
protected override async Task<MysqlEntityMovie> GetEntityAsync(string id)
4442
=> await Context.Movies.AsNoTracking().SingleOrDefaultAsync(m => m.Id == id);

tests/CommunityToolkit.Datasync.Server.Test/Live/MySQL_Controller_Tests.cs

+5-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using CommunityToolkit.Datasync.Server.EntityFrameworkCore;
66
using CommunityToolkit.Datasync.Server.Test.Helpers;
77
using CommunityToolkit.Datasync.TestCommon.Databases;
8+
using CommunityToolkit.Datasync.TestCommon.Fixtures;
89
using Microsoft.EntityFrameworkCore;
910
using Microsoft.VisualStudio.TestPlatform.Utilities;
1011
using Xunit.Abstractions;
@@ -13,24 +14,16 @@ namespace CommunityToolkit.Datasync.Server.Test.Live;
1314

1415
[ExcludeFromCodeCoverage]
1516
[Collection("LiveTestsCollection")]
16-
public class MySQL_Controller_Tests(DatabaseFixture fixture, ITestOutputHelper output) : LiveControllerTests<MysqlEntityMovie>, IAsyncLifetime
17+
public class MySQL_Controller_Tests(MySqlDatabaseFixture fixture, ITestOutputHelper output) : LiveControllerTests<MysqlEntityMovie>, IClassFixture<MySqlDatabaseFixture>, IAsyncLifetime
1718
{
1819
#region Setup
1920
private readonly Random random = new();
2021
private List<MysqlEntityMovie> movies = [];
2122

2223
public async Task InitializeAsync()
2324
{
24-
if (!string.IsNullOrEmpty(ConnectionStrings.MySql))
25-
{
26-
// Note: we don't clear entities on every run to speed up the test runs. This can only be done because
27-
// the tests are read-only (associated with the query and get capabilities). If the test being run writes
28-
// to the database then change clearEntities to true.
29-
output.WriteLine($"MysqlIsInitialized = {fixture.MysqlIsInitialized}");
30-
Context = await MysqlDbContext.CreateContextAsync(ConnectionStrings.MySql, output, clearEntities: !fixture.MysqlIsInitialized);
31-
this.movies = await Context.Movies.AsNoTracking().ToListAsync();
32-
fixture.MysqlIsInitialized = true;
33-
}
25+
Context = await MysqlDbContext.CreateContextAsync(fixture.ConnectionString, output);
26+
this.movies = await Context.Movies.AsNoTracking().ToListAsync();
3427
}
3528

3629
public async Task DisposeAsync()
@@ -45,7 +38,7 @@ public async Task DisposeAsync()
4538

4639
protected override string DriverName { get; } = "MySQL";
4740

48-
protected override bool CanRunLiveTests() => !string.IsNullOrEmpty(ConnectionStrings.MySql);
41+
protected override bool CanRunLiveTests() => true;
4942

5043
protected override async Task<MysqlEntityMovie> GetEntityAsync(string id)
5144
=> await Context.Movies.AsNoTracking().SingleOrDefaultAsync(m => m.Id == id);

tests/CommunityToolkit.Datasync.TestCommon/CommunityToolkit.Datasync.TestCommon.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<IsTestProject>false</IsTestProject>
44
</PropertyGroup>
@@ -20,6 +20,7 @@
2020
<PackageReference Include="Microsoft.Spatial" />
2121
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
2222
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" />
23+
<PackageReference Include="TestContainers.MySql" />
2324
</ItemGroup>
2425

2526
<ItemGroup>

tests/CommunityToolkit.Datasync.TestCommon/Databases/ConnectionStrings.cs

-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ public static class ConnectionStrings
1111
public static readonly string CosmosDb = Environment.GetEnvironmentVariable("COSMOS_CONNECTION_STRING");
1212
public static readonly string MongoCommunity = Environment.GetEnvironmentVariable("MONGOACI_CONNECTION_STRING");
1313
public static readonly string CosmosMongo = Environment.GetEnvironmentVariable("MONGO_CONNECTION_STRING");
14-
public static readonly string MySql = Environment.GetEnvironmentVariable("MYSQL_CONNECTION_STRING");
1514
public static readonly string PgSql = Environment.GetEnvironmentVariable("PGSQL_CONNECTION_STRING");
16-
1715
public static readonly string Service = Environment.GetEnvironmentVariable("SERVICE_ENDPOINT");
1816
public static readonly bool EnableLogging = (Environment.GetEnvironmentVariable("ENABLE_SQL_LOGGING") ?? "false") == "true";
1917
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Testcontainers.MySql;
6+
using Xunit;
7+
8+
namespace CommunityToolkit.Datasync.TestCommon.Fixtures;
9+
10+
/// <summary>
11+
/// A test fixture for impementing a MySQL database using Testcontainers.
12+
/// </summary>
13+
[ExcludeFromCodeCoverage]
14+
public class MySqlDatabaseFixture : IAsyncLifetime
15+
{
16+
private readonly MySqlContainer _container;
17+
18+
public MySqlDatabaseFixture()
19+
{
20+
this._container = new MySqlBuilder()
21+
.WithImage("mysql:lts-oracle")
22+
.WithCleanUp(true)
23+
.WithUsername("testuser")
24+
.WithPassword("testpassword")
25+
.WithDatabase("testdb")
26+
.Build();
27+
}
28+
29+
/// <inheritdoc />
30+
public async Task DisposeAsync()
31+
{
32+
if (this._container is not null)
33+
{
34+
await this._container.DisposeAsync();
35+
}
36+
}
37+
38+
/// <inheritdoc />
39+
public async Task InitializeAsync()
40+
{
41+
await this._container.StartAsync();
42+
ConnectionString = this._container.GetConnectionString();
43+
}
44+
45+
/// <summary>
46+
/// The connection string for the MySQL database.
47+
/// </summary>
48+
public string ConnectionString { get; private set; } = string.Empty;
49+
}

tests/CommunityToolkit.Datasync.TestCommon/Fixtures/MySqlTestFixture.cs

Whitespace-only changes.

0 commit comments

Comments
 (0)