From b34c2db81743a0a3ede7fce29ee577d26a87650d Mon Sep 17 00:00:00 2001 From: Jimmy Bogard Date: Wed, 29 May 2024 14:24:27 -0500 Subject: [PATCH] Switching to testcontainers --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- .../AsyncEnumerableDataReaderTests.cs | 22 +++-- src/BulkWriter.Tests/BulkWriter.Tests.csproj | 1 + .../BulkWriterAsyncEnumerableTests.cs | 16 ++-- src/BulkWriter.Tests/BulkWriterAsyncTests.cs | 17 ++-- .../BulkWriterInitializationTests.cs | 21 +++-- src/BulkWriter.Tests/BulkWriterTests.cs | 77 ++++++++--------- src/BulkWriter.Tests/DbContainerFixture.cs | 82 +++++++++++++++++++ .../EnumerableDataReaderTests.cs | 22 +++-- .../Pipeline/AsyncEtlPipelineTests.cs | 22 +++-- .../Pipeline/EtlPipelineTests.cs | 22 +++-- src/BulkWriter.Tests/TestHelpers.cs | 63 -------------- 13 files changed, 220 insertions(+), 149 deletions(-) create mode 100644 src/BulkWriter.Tests/DbContainerFixture.cs delete mode 100644 src/BulkWriter.Tests/TestHelpers.cs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a477cc..495db22 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: - master jobs: build: - runs-on: windows-latest + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67f5900..26b427f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: - '*.*.*' jobs: build: - runs-on: windows-latest + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 diff --git a/src/BulkWriter.Tests/AsyncEnumerableDataReaderTests.cs b/src/BulkWriter.Tests/AsyncEnumerableDataReaderTests.cs index ffe0049..f4e660c 100644 --- a/src/BulkWriter.Tests/AsyncEnumerableDataReaderTests.cs +++ b/src/BulkWriter.Tests/AsyncEnumerableDataReaderTests.cs @@ -9,9 +9,10 @@ namespace BulkWriter.Tests { + [Collection(nameof(DbContainerFixture))] public class AsyncEnumerableDataReaderTests : IAsyncLifetime { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly string _connectionString; private readonly string _tableName = nameof(MyTestClass); private readonly string _customOrderTableName = nameof(MyCustomOrderTestClass); @@ -22,17 +23,22 @@ public class AsyncEnumerableDataReaderTests : IAsyncLifetime private readonly IAsyncEnumerable _customOrderEnumerable; private readonly AsyncEnumerableDataReader _customOrderDataReader; - public AsyncEnumerableDataReaderTests() + private readonly DbContainerFixture _fixture; + + public AsyncEnumerableDataReaderTests(DbContainerFixture fixture) { + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + // // Setup for testing default mapping using the source entity's property positions as the ordinals. // _enumerable = new[] { new MyTestClass() }.ToAsyncEnumerable(); - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + _tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Name] [nvarchar](50) NULL," + @@ -54,9 +60,9 @@ public AsyncEnumerableDataReaderTests() _customOrderEnumerable = new[] { new MyCustomOrderTestClass() }.ToAsyncEnumerable(); - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_customOrderTableName}]"); + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_customOrderTableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + _customOrderTableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[FirstName] [nvarchar](50) NULL," + @@ -367,8 +373,8 @@ public async Task InitializeAsync() public Task DisposeAsync() { - TestHelpers.ExecuteNonQuery(_connectionString, "DROP TABLE " + _tableName); - TestHelpers.ExecuteNonQuery(_connectionString, "DROP TABLE " + _customOrderTableName); + _fixture.ExecuteNonQuery(_connectionString, "DROP TABLE " + _tableName); + _fixture.ExecuteNonQuery(_connectionString, "DROP TABLE " + _customOrderTableName); return Task.CompletedTask; } diff --git a/src/BulkWriter.Tests/BulkWriter.Tests.csproj b/src/BulkWriter.Tests/BulkWriter.Tests.csproj index 00c72e0..52cda0a 100644 --- a/src/BulkWriter.Tests/BulkWriter.Tests.csproj +++ b/src/BulkWriter.Tests/BulkWriter.Tests.csproj @@ -7,6 +7,7 @@ + all diff --git a/src/BulkWriter.Tests/BulkWriterAsyncEnumerableTests.cs b/src/BulkWriter.Tests/BulkWriterAsyncEnumerableTests.cs index 756ad0d..ac53dbf 100644 --- a/src/BulkWriter.Tests/BulkWriterAsyncEnumerableTests.cs +++ b/src/BulkWriter.Tests/BulkWriterAsyncEnumerableTests.cs @@ -4,9 +4,10 @@ namespace BulkWriter.Tests { + [Collection(nameof(DbContainerFixture))] public class BulkWriterAsyncEnumerableTests { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly string _connectionString; private readonly string _tableName = nameof(BulkWriterAsyncTestsMyTestClass); public class BulkWriterAsyncTestsMyTestClass @@ -16,11 +17,16 @@ public class BulkWriterAsyncTestsMyTestClass public string Name { get; set; } } - public BulkWriterAsyncEnumerableTests() + private readonly DbContainerFixture _fixture; + + public BulkWriterAsyncEnumerableTests(DbContainerFixture fixture) { - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + _tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Name] [nvarchar](50) NULL," + @@ -40,7 +46,7 @@ public async Task CanWriteSync() await writer.WriteToDatabaseAsync(items); - var count = (int) await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {_tableName}"); + var count = (int) await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {_tableName}"); Assert.Equal(1000, count); } diff --git a/src/BulkWriter.Tests/BulkWriterAsyncTests.cs b/src/BulkWriter.Tests/BulkWriterAsyncTests.cs index e3b38b7..90aff89 100644 --- a/src/BulkWriter.Tests/BulkWriterAsyncTests.cs +++ b/src/BulkWriter.Tests/BulkWriterAsyncTests.cs @@ -4,9 +4,10 @@ namespace BulkWriter.Tests { + [Collection(nameof(DbContainerFixture))] public class BulkWriterAsyncTests { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly string _connectionString; private readonly string _tableName = nameof(BulkWriterAsyncTestsMyTestClass); public class BulkWriterAsyncTestsMyTestClass @@ -16,11 +17,15 @@ public class BulkWriterAsyncTestsMyTestClass public string Name { get; set; } } - public BulkWriterAsyncTests() + private readonly DbContainerFixture _fixture; + + public BulkWriterAsyncTests(DbContainerFixture fixture) { - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + _tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Name] [nvarchar](50) NULL," + @@ -37,9 +42,9 @@ public async Task CanWriteSync() await writer.WriteToDatabaseAsync(items); - var count = (int) await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {_tableName}"); + var count = (int) await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {_tableName}"); Assert.Equal(1000, count); } } -} \ No newline at end of file +} diff --git a/src/BulkWriter.Tests/BulkWriterInitializationTests.cs b/src/BulkWriter.Tests/BulkWriterInitializationTests.cs index 637a061..ebc9f59 100644 --- a/src/BulkWriter.Tests/BulkWriterInitializationTests.cs +++ b/src/BulkWriter.Tests/BulkWriterInitializationTests.cs @@ -5,9 +5,10 @@ namespace BulkWriter.Tests { + [Collection(nameof(DbContainerFixture))] public class BulkWriterInitializationTests { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly string _connectionString; public class BulkWriterInitializationTestsMyTestClass { @@ -15,6 +16,14 @@ public class BulkWriterInitializationTestsMyTestClass public string Name { get; set; } } + + private readonly DbContainerFixture _fixture; + + public BulkWriterInitializationTests(DbContainerFixture fixture) + { + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + } [Table("TestClass2")] public class BulkWriterInitializationTestsMyTestClassAnnotation @@ -51,7 +60,7 @@ public async Task CanSetBulkCopyParameters() writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(10, count); Assert.True(setupCallbackInvoked); @@ -83,7 +92,7 @@ public async Task CanSetBulkCopyParameters_Respects_Table_Annotation() writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName }"); + var count = (int)await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName }"); Assert.Equal(10, count); Assert.True(setupCallbackInvoked); @@ -91,9 +100,9 @@ public async Task CanSetBulkCopyParameters_Respects_Table_Annotation() private string DropCreate(string tableName) { - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{tableName}]"); + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Name] [nvarchar](50) NULL," + @@ -103,4 +112,4 @@ private string DropCreate(string tableName) return tableName; } } -} \ No newline at end of file +} diff --git a/src/BulkWriter.Tests/BulkWriterTests.cs b/src/BulkWriter.Tests/BulkWriterTests.cs index 6fd1a3e..1dd80b5 100644 --- a/src/BulkWriter.Tests/BulkWriterTests.cs +++ b/src/BulkWriter.Tests/BulkWriterTests.cs @@ -8,9 +8,12 @@ namespace BulkWriter.Tests { + [Collection(nameof(DbContainerFixture))] public class BulkWriterTests { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly DbContainerFixture _fixture; + + public BulkWriterTests(DbContainerFixture fixture) => _fixture = fixture; public class BulkWriterTestsMyTestClass { @@ -30,15 +33,15 @@ public class BulkWriterTestsMyTestClassWithKey [Fact] public async Task CanWriteSync() { - string tableName = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClass)); + string tableName = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClass)); - var writer = new BulkWriter(_connectionString); + var writer = new BulkWriter(_fixture.TestConnectionString); var items = Enumerable.Range(1, 1000).Select(i => new BulkWriterTestsMyTestClass { Id = i, Name = "Bob" }); writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar($"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(1000, count); } @@ -46,11 +49,11 @@ public async Task CanWriteSync() [Fact] public async Task CanWriteSyncWithOptions() { - var tableName = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClass)); - var tableNameWithKey = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClassWithKey)); + var tableName = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClass)); + var tableNameWithKey = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClassWithKey)); - var writer = new BulkWriter(_connectionString); - var writerWithOptions = new BulkWriter(_connectionString, SqlBulkCopyOptions.KeepIdentity); + var writer = new BulkWriter(_fixture.TestConnectionString); + var writerWithOptions = new BulkWriter(_fixture.TestConnectionString, SqlBulkCopyOptions.KeepIdentity); var items = Enumerable.Range(11, 20).Select(i => new BulkWriterTestsMyTestClass { Id = i, Name = "Bob" }); var itemsWithKey = Enumerable.Range(11, 20).Select(i => new BulkWriterTestsMyTestClassWithKey { Id = i, Name = "Bob" }); @@ -58,8 +61,8 @@ public async Task CanWriteSyncWithOptions() writer.WriteToDatabase(items); writerWithOptions.WriteToDatabase(itemsWithKey); - var minId = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT MIN(Id) FROM {tableName}"); - var minIdWithKey = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT MIN(Id) FROM {tableNameWithKey}"); + var minId = (int)await _fixture.ExecuteScalar($"SELECT MIN(Id) FROM {tableName}"); + var minIdWithKey = (int)await _fixture.ExecuteScalar($"SELECT MIN(Id) FROM {tableNameWithKey}"); Assert.Equal(1, minId); Assert.Equal(11, minIdWithKey); @@ -68,9 +71,9 @@ public async Task CanWriteSyncWithOptions() [Fact] public async Task CanWriteSyncWithExistingConnection() { - string tableName = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClass)); + string tableName = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClass)); - using (var connection = new SqlConnection(_connectionString)) + using (var connection = new SqlConnection(_fixture.TestConnectionString)) { await connection.OpenAsync(); @@ -81,7 +84,7 @@ public async Task CanWriteSyncWithExistingConnection() writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(connection, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar(connection, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(1000, count); } @@ -90,9 +93,9 @@ public async Task CanWriteSyncWithExistingConnection() [Fact] public async Task CanWriteSyncWithExistingConnectionAndTransaction() { - string tableName = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClass)); + string tableName = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClass)); - using (var connection = new SqlConnection(_connectionString)) + using (var connection = new SqlConnection(_fixture.TestConnectionString)) { await connection.OpenAsync(); @@ -106,13 +109,13 @@ public async Task CanWriteSyncWithExistingConnectionAndTransaction() writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(connection, $"SELECT COUNT(1) FROM {tableName}", transaction); + var count = (int)await _fixture.ExecuteScalar(connection, $"SELECT COUNT(1) FROM {tableName}", transaction); Assert.Equal(1000, count); transaction.Rollback(); - count = (int)await TestHelpers.ExecuteScalar(connection, $"SELECT COUNT(1) FROM {tableName}"); + count = (int)await _fixture.ExecuteScalar(connection, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(0, count); } @@ -122,10 +125,10 @@ public async Task CanWriteSyncWithExistingConnectionAndTransaction() [Fact] public async Task CanWriteSyncWithExistingConnectionAndTransactionAndOptions() { - var tableName = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClass)); - var tableNameWithKey = TestHelpers.DropCreate(nameof(BulkWriterTestsMyTestClassWithKey)); + var tableName = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClass)); + var tableNameWithKey = _fixture.DropCreate(nameof(BulkWriterTestsMyTestClassWithKey)); - using (var connection = new SqlConnection(_connectionString)) + using (var connection = new SqlConnection(_fixture.TestConnectionString)) { await connection.OpenAsync(); @@ -140,16 +143,16 @@ public async Task CanWriteSyncWithExistingConnectionAndTransactionAndOptions() writer.WriteToDatabase(items); writerWithOptions.WriteToDatabase(itemsWithKey); - var minId = (int?)await TestHelpers.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableName}", transaction); - var minIdWithKey = (int?)await TestHelpers.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableNameWithKey}", transaction); + var minId = (int?)await _fixture.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableName}", transaction); + var minIdWithKey = (int?)await _fixture.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableNameWithKey}", transaction); Assert.Equal(1, minId); Assert.Equal(11, minIdWithKey); transaction.Rollback(); - var emptyMinId = await TestHelpers.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableName}"); - var emptyMinIdWithKey = await TestHelpers.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableNameWithKey}"); + var emptyMinId = await _fixture.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableName}"); + var emptyMinIdWithKey = await _fixture.ExecuteScalar(connection, $"SELECT MIN(Id) FROM {tableNameWithKey}"); Assert.Equal(emptyMinId, System.DBNull.Value); Assert.Equal(emptyMinIdWithKey, System.DBNull.Value); @@ -175,15 +178,15 @@ public class OrdinalAndColumnNameExampleType [Fact] public async Task Should_Handle_Both_Ordinal_And_ColumnName_For_Destination_Mapping() { - string tableName = TestHelpers.DropCreate(nameof(OrdinalAndColumnNameExampleType)); + string tableName = _fixture.DropCreate(nameof(OrdinalAndColumnNameExampleType)); - var writer = new BulkWriter(_connectionString); + var writer = new BulkWriter(_fixture.TestConnectionString); var items = new[] { new OrdinalAndColumnNameExampleType { Id = 1, Name2 = "Bob" } }; writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar($"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(1, count); } @@ -198,21 +201,21 @@ public class MyTestClassForNvarCharMax public async Task Should_Handle_Column_Nvarchar_With_Length_Max() { string tableName = nameof(MyTestClassForNvarCharMax); - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery($"DROP TABLE IF EXISTS [dbo].[{tableName}]"); + _fixture.ExecuteNonQuery( "CREATE TABLE [dbo].[" + tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Name] [nvarchar](MAX) NULL," + "CONSTRAINT [PK_" + tableName + "] PRIMARY KEY CLUSTERED ([Id] ASC)" + ")"); - var writer = new BulkWriter(_connectionString); + var writer = new BulkWriter(_fixture.TestConnectionString); var items = new[] { new MyTestClassForNvarCharMax { Id = 1, Name = "Bob" } }; writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar($"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(1, count); } @@ -228,24 +231,24 @@ public async Task Should_Handle_Column_VarBinary_Large() { string tableName = nameof(MyTestClassForVarBinary); - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery($"DROP TABLE IF EXISTS [dbo].[{tableName}]"); + _fixture.ExecuteNonQuery( "CREATE TABLE [dbo].[" + tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Data] [varbinary](MAX) NULL," + "CONSTRAINT [PK_" + tableName + "] PRIMARY KEY CLUSTERED ([Id] ASC)" + ")"); - var writer = new BulkWriter(_connectionString); + var writer = new BulkWriter(_fixture.TestConnectionString); var items = new[] { new MyTestClassForVarBinary { Id = 1, Data = new byte[1024 * 1024 * 1] } }; new Random().NextBytes(items.First().Data); writer.WriteToDatabase(items); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); - var data = (byte[])await TestHelpers.ExecuteScalar(_connectionString, $"SELECT TOP 1 Data FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar($"SELECT COUNT(1) FROM {tableName}"); + var data = (byte[])await _fixture.ExecuteScalar($"SELECT TOP 1 Data FROM {tableName}"); Assert.Equal(items.First().Data, data); Assert.Equal(1, count); } } -} \ No newline at end of file +} diff --git a/src/BulkWriter.Tests/DbContainerFixture.cs b/src/BulkWriter.Tests/DbContainerFixture.cs new file mode 100644 index 0000000..8cd829d --- /dev/null +++ b/src/BulkWriter.Tests/DbContainerFixture.cs @@ -0,0 +1,82 @@ +using Microsoft.Data.SqlClient; +using System.Threading.Tasks; +using Testcontainers.MsSql; +using Xunit; + +namespace BulkWriter.Tests; + + +[CollectionDefinition(nameof(DbContainerFixture))] +public class DbContainerFixtureCollection : ICollectionFixture { } + +public class DbContainerFixture : IAsyncLifetime +{ + public MsSqlContainer SqlContainer { get; } = new MsSqlBuilder().Build(); + public string TestConnectionString { get; private set; } + + public async Task InitializeAsync() + { + await SqlContainer.StartAsync(); + + ExecuteNonQuery(SqlContainer.GetConnectionString(), @"IF NOT EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N'BulkWriter.Tests') + CREATE DATABASE [BulkWriter.Tests]"); + + var builder = new SqlConnectionStringBuilder(SqlContainer.GetConnectionString()) + { + InitialCatalog = "BulkWriter.Tests" + }; + + TestConnectionString = builder.ToString(); + } + + public Task DisposeAsync() + => SqlContainer.DisposeAsync().AsTask(); + + public void ExecuteNonQuery(string commandText) => ExecuteNonQuery(TestConnectionString, commandText); + + public void ExecuteNonQuery(string connectionString, string commandText) + { + using (var sqlConnection = new SqlConnection(connectionString)) + { + using (var command = new SqlCommand(commandText, sqlConnection)) + { + sqlConnection.Open(); + command.ExecuteNonQuery(); + } + } + } + + public Task ExecuteScalar(string commandText) => ExecuteScalar(TestConnectionString, commandText); + + public async Task ExecuteScalar(string connectionString, string commandText) + { + using (var sqlConnection = new SqlConnection(connectionString)) + { + await sqlConnection.OpenAsync(); + return await ExecuteScalar(sqlConnection, commandText); + } + } + + public async Task ExecuteScalar(SqlConnection sqlConnection, string commandText, SqlTransaction transaction = null) + { + using (var command = new SqlCommand(commandText, sqlConnection, transaction)) + { + return await command.ExecuteScalarAsync(); + } + } + + public string DropCreate(string tableName) + { + ExecuteNonQuery(TestConnectionString, $"DROP TABLE IF EXISTS [dbo].[{tableName}]"); + + ExecuteNonQuery(TestConnectionString, + "CREATE TABLE [dbo].[" + tableName + "](" + + "[Id] [int] IDENTITY(1,1) NOT NULL," + + "[Name] [nvarchar](50) NULL," + + "CONSTRAINT [PK_" + tableName + "] PRIMARY KEY CLUSTERED ([Id] ASC)" + + ")"); + + return tableName; + } + +} diff --git a/src/BulkWriter.Tests/EnumerableDataReaderTests.cs b/src/BulkWriter.Tests/EnumerableDataReaderTests.cs index 3c10c96..d8809f3 100644 --- a/src/BulkWriter.Tests/EnumerableDataReaderTests.cs +++ b/src/BulkWriter.Tests/EnumerableDataReaderTests.cs @@ -8,9 +8,10 @@ namespace BulkWriter.Tests { + [Collection(nameof(DbContainerFixture))] public class EnumerableDataReaderTests : IDisposable { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly string _connectionString; private readonly string _tableName = nameof(MyTestClass); private readonly string _customOrderTableName = nameof(MyCustomOrderTestClass); @@ -21,17 +22,22 @@ public class EnumerableDataReaderTests : IDisposable private readonly IEnumerable _customOrderEnumerable; private readonly EnumerableDataReader _customOrderDataReader; - public EnumerableDataReaderTests() + private readonly DbContainerFixture _fixture; + + public EnumerableDataReaderTests(DbContainerFixture fixture) { + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + // // Setup for testing default mapping using the source entity's property positions as the ordinals. // _enumerable = new[] { new MyTestClass() }; - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_tableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + _tableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[Name] [nvarchar](50) NULL," + @@ -54,9 +60,9 @@ public EnumerableDataReaderTests() _customOrderEnumerable = new[] { new MyCustomOrderTestClass() }; - TestHelpers.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_customOrderTableName}]"); + _fixture.ExecuteNonQuery(_connectionString, $"DROP TABLE IF EXISTS [dbo].[{_customOrderTableName}]"); - TestHelpers.ExecuteNonQuery(_connectionString, + _fixture.ExecuteNonQuery(_connectionString, "CREATE TABLE [dbo].[" + _customOrderTableName + "](" + "[Id] [int] IDENTITY(1,1) NOT NULL," + "[FirstName] [nvarchar](50) NULL," + @@ -73,8 +79,8 @@ public EnumerableDataReaderTests() public void Dispose() { - TestHelpers.ExecuteNonQuery(_connectionString, "DROP TABLE " + _tableName); - TestHelpers.ExecuteNonQuery(_connectionString, "DROP TABLE " + _customOrderTableName); + _fixture.ExecuteNonQuery(_connectionString, "DROP TABLE " + _tableName); + _fixture.ExecuteNonQuery(_connectionString, "DROP TABLE " + _customOrderTableName); } [Fact] diff --git a/src/BulkWriter.Tests/Pipeline/AsyncEtlPipelineTests.cs b/src/BulkWriter.Tests/Pipeline/AsyncEtlPipelineTests.cs index 73fb57e..7ee2586 100644 --- a/src/BulkWriter.Tests/Pipeline/AsyncEtlPipelineTests.cs +++ b/src/BulkWriter.Tests/Pipeline/AsyncEtlPipelineTests.cs @@ -9,9 +9,17 @@ namespace BulkWriter.Tests.Pipeline { + [Collection(nameof(DbContainerFixture))] public class AsyncEtlPipelineTests { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly DbContainerFixture _fixture; + private readonly string _connectionString; + + public AsyncEtlPipelineTests(DbContainerFixture fixture) + { + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + } public class PipelineTestsMyTestClass { @@ -29,7 +37,7 @@ public class PipelineTestsOtherTestClass [Fact] public async Task WritesToBulkWriter() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -44,7 +52,7 @@ public async Task WritesToBulkWriter() await pipeline.ExecuteAsync(); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(1000, count); } @@ -53,7 +61,7 @@ public async Task WritesToBulkWriter() [Fact] public async Task ThrowsWhenAStepThrows() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -76,7 +84,7 @@ public async Task ThrowsWhenAStepThrows() [Fact] public async Task RaisesExceptionsForAllStepsThatThrow() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -117,7 +125,7 @@ public async Task RaisesExceptionsForAllStepsThatThrow() [Fact] public async Task PartiallyCompletesWhenAStepThrows() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -139,7 +147,7 @@ public async Task PartiallyCompletesWhenAStepThrows() var pipelineTask = pipeline.ExecuteAsync(); await Assert.ThrowsAsync(() => pipelineTask); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(500, count); } } diff --git a/src/BulkWriter.Tests/Pipeline/EtlPipelineTests.cs b/src/BulkWriter.Tests/Pipeline/EtlPipelineTests.cs index 1ed7709..11e3726 100644 --- a/src/BulkWriter.Tests/Pipeline/EtlPipelineTests.cs +++ b/src/BulkWriter.Tests/Pipeline/EtlPipelineTests.cs @@ -9,10 +9,18 @@ namespace BulkWriter.Tests.Pipeline { + [Collection(nameof(DbContainerFixture))] public class EtlPipelineTests { - private readonly string _connectionString = TestHelpers.ConnectionString; + private readonly DbContainerFixture _fixture; + private readonly string _connectionString; + public EtlPipelineTests(DbContainerFixture fixture) + { + _fixture = fixture; + _connectionString = fixture.TestConnectionString; + } + public class PipelineTestsMyTestClass { public int Id { get; set; } @@ -29,7 +37,7 @@ public class PipelineTestsOtherTestClass [Fact] public async Task WritesToBulkWriter() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -40,7 +48,7 @@ public async Task WritesToBulkWriter() await pipeline.ExecuteAsync(); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(1000, count); } @@ -49,7 +57,7 @@ public async Task WritesToBulkWriter() [Fact] public async Task ThrowsWhenAStepThrows() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -68,7 +76,7 @@ public async Task ThrowsWhenAStepThrows() [Fact] public async Task RaisesExceptionsForAllStepsThatThrow() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -105,7 +113,7 @@ public async Task RaisesExceptionsForAllStepsThatThrow() [Fact] public async Task PartiallyCompletesWhenAStepThrows() { - var tableName = TestHelpers.DropCreate(nameof(PipelineTestsMyTestClass)); + var tableName = _fixture.DropCreate(nameof(PipelineTestsMyTestClass)); using (var writer = new BulkWriter(_connectionString)) { @@ -123,7 +131,7 @@ public async Task PartiallyCompletesWhenAStepThrows() var pipelineTask = pipeline.ExecuteAsync(); await Assert.ThrowsAsync(() => pipelineTask); - var count = (int)await TestHelpers.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); + var count = (int)await _fixture.ExecuteScalar(_connectionString, $"SELECT COUNT(1) FROM {tableName}"); Assert.Equal(500, count); } } diff --git a/src/BulkWriter.Tests/TestHelpers.cs b/src/BulkWriter.Tests/TestHelpers.cs deleted file mode 100644 index 2fb5053..0000000 --- a/src/BulkWriter.Tests/TestHelpers.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Microsoft.Data.SqlClient; -using System.Threading.Tasks; - -namespace BulkWriter.Tests -{ - internal static class TestHelpers - { - static TestHelpers() - { - ConnectionString = @"Data Source=(localdb)\mssqllocaldb;Database=BulkWriter.Tests;Trusted_Connection=True;"; - - string admin = @"Data Source=(localdb)\mssqllocaldb;Trusted_Connection=True;"; - ExecuteNonQuery(admin, @"IF NOT EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N'BulkWriter.Tests') -CREATE DATABASE [BulkWriter.Tests]"); - } - - - public static void ExecuteNonQuery(string connectionString, string commandText) - { - using (var sqlConnection = new SqlConnection(connectionString)) - { - using (var command = new SqlCommand(commandText, sqlConnection)) - { - sqlConnection.Open(); - command.ExecuteNonQuery(); - } - } - } - - public static async Task ExecuteScalar(string connectionString, string commandText) - { - using (var sqlConnection = new SqlConnection(connectionString)) - { - await sqlConnection.OpenAsync(); - return await ExecuteScalar(sqlConnection, commandText); - } - } - - public static async Task ExecuteScalar(SqlConnection sqlConnection, string commandText, SqlTransaction transaction = null) - { - using (var command = new SqlCommand(commandText, sqlConnection, transaction)) - { - return await command.ExecuteScalarAsync(); - } - } - - public static string DropCreate(string tableName) - { - ExecuteNonQuery(ConnectionString, $"DROP TABLE IF EXISTS [dbo].[{tableName}]"); - - ExecuteNonQuery(ConnectionString, - "CREATE TABLE [dbo].[" + tableName + "](" + - "[Id] [int] IDENTITY(1,1) NOT NULL," + - "[Name] [nvarchar](50) NULL," + - "CONSTRAINT [PK_" + tableName + "] PRIMARY KEY CLUSTERED ([Id] ASC)" + - ")"); - - return tableName; - } - - public static string ConnectionString { get; } - } -} \ No newline at end of file