Skip to content

Commit

Permalink
Scope SqlConnection per test in Dibix.Testing
Browse files Browse the repository at this point in the history
  • Loading branch information
C0nquistadore committed Jan 7, 2025
1 parent 4cb4396 commit ce16262
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ private static void GenerateSource(SourceProductionContext sourceProductionConte
AnalyzerConfigOptions options = analyzerConfigOptionsProvider.GlobalOptions;
string rootNamespace = GetRequiredMetadataProperty<string>(options, "build_property.rootnamespace");

ImmutableArray<EmbeddedResourceItem> items = files.Where(x => ShouldGenerateAccessor(analyzerConfigOptionsProvider, x))
.Select(x => CreateItem(x, analyzerConfigOptionsProvider))
.ToImmutableArray();
ImmutableArray<EmbeddedResourceItem> items =
[
..files.Where(x => ShouldGenerateAccessor(analyzerConfigOptionsProvider, x))
.Select(x => CreateItem(x, analyzerConfigOptionsProvider))
];
if (!items.Any())
return;

Expand Down
22 changes: 7 additions & 15 deletions src/Dibix.Testing/Data/DatabaseTestBase.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -12,7 +10,7 @@ namespace Dibix.Testing.Data
public abstract class DatabaseTestBase<TConfiguration> : TestBase<TConfiguration>, IDisposable where TConfiguration : DatabaseConfigurationBase, new()
{
#region Fields
private readonly Lazy<IDatabaseAccessorFactory> _databaseAccessorFactoryAccessor;
private readonly Lazy<IDisposableDatabaseAccessorFactory> _databaseAccessorFactoryAccessor;
private Action _removeTraceListener;
#endregion

Expand All @@ -23,7 +21,7 @@ namespace Dibix.Testing.Data
#region Constructor
protected DatabaseTestBase()
{
this._databaseAccessorFactoryAccessor = new Lazy<IDatabaseAccessorFactory>(() => CreateDatabaseAccessorFactory());
this._databaseAccessorFactoryAccessor = new Lazy<IDisposableDatabaseAccessorFactory>(() => CreateDatabaseAccessorFactoryCore());
}
#endregion

Expand Down Expand Up @@ -56,10 +54,12 @@ protected async Task ExecuteStoredProcedure(string storedProcedureName, Action<I
}
}

protected IDatabaseAccessorFactory CreateDatabaseAccessorFactory(int? commandTimeout = 30) => DatabaseTestUtility.CreateDatabaseAccessorFactory(base.Configuration, commandTimeout);
protected IDatabaseAccessorFactory CreateDatabaseAccessorFactory(int? commandTimeout = 30) => CreateDatabaseAccessorFactoryCore(commandTimeout);
#endregion

#region Private Methods
private IDisposableDatabaseAccessorFactory CreateDatabaseAccessorFactoryCore(int? commandTimeout = 30) => DatabaseTestUtility.CreateDatabaseAccessorFactory(base.Configuration, commandTimeout);

private static TraceSource GetDibixTraceSource()
{
const string fieldName = "TraceSource";
Expand All @@ -76,16 +76,6 @@ private static TraceSource GetDibixTraceSource()
traceSource.Switch.Level = SourceLevels.Information;
return traceSource;
}

private static TraceSource GetDibixTraceSource_()
{
FieldInfo traceSourcesField = typeof(TraceSource).GetField("s_tracesources", BindingFlags.NonPublic | BindingFlags.Static);
ICollection<WeakReference> traceSources = (ICollection<WeakReference>)traceSourcesField.GetValue(null);
TraceSource traceSource = traceSources.Select(x => x.Target)
.Cast<TraceSource>()
.Single(x => x.Name == "Dibix.Sql");
return traceSource;
}
#endregion

#region IDisposable Members
Expand All @@ -95,6 +85,8 @@ protected override void Dispose(bool disposing)
if (disposing)
{
this._removeTraceListener?.Invoke();
if (_databaseAccessorFactoryAccessor.IsValueCreated)
_databaseAccessorFactoryAccessor.Value.Dispose();
}
}
#endregion
Expand Down
39 changes: 26 additions & 13 deletions src/Dibix.Testing/Data/DatabaseTestUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,12 @@
using System.Threading;
using System.Threading.Tasks;
using Dapper;
using Dibix.Testing.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Dibix.Testing.Data
{
public static class DatabaseTestUtility
internal static class DatabaseTestUtility
{
public static IDatabaseAccessorFactory CreateDatabaseAccessorFactory<TConfiguration>(TestContext testContext, TestConfigurationValidationBehavior configurationValidationBehavior = TestDefaults.ValidationBehavior) where TConfiguration : DatabaseConfigurationBase, new()
{
TConfiguration configuration = TestConfigurationLoader.Load<TConfiguration>(testContext, configurationValidationBehavior);
return CreateDatabaseAccessorFactory(configuration);
}
public static IDatabaseAccessorFactory CreateDatabaseAccessorFactory<TConfiguration>(TConfiguration configuration, int? defaultCommandTimeout = null) where TConfiguration : DatabaseConfigurationBase, new()
public static IDisposableDatabaseAccessorFactory CreateDatabaseAccessorFactory<TConfiguration>(TConfiguration configuration, int? defaultCommandTimeout = null) where TConfiguration : DatabaseConfigurationBase, new()
{
return new DapperDatabaseAccessorFactory(configuration.Database.ConnectionString, RaiseErrorWithNoWaitBehavior.ExecuteScalar, defaultCommandTimeout);
}
Expand All @@ -40,22 +33,27 @@ private enum RaiseErrorWithNoWaitBehavior
ExecuteScalar
}

private sealed class DapperDatabaseAccessorFactory : IDatabaseAccessorFactory
private sealed class DapperDatabaseAccessorFactory : IDisposableDatabaseAccessorFactory, IDatabaseAccessorFactory, IDisposable
{
private readonly string _connectionString;
private readonly RaiseErrorWithNoWaitBehavior _raiseErrorWithNoWaitBehavior;
private readonly int? _defaultCommandTimeout;
private readonly Lazy<SqlConnection> _connectionAccessor;

public DapperDatabaseAccessorFactory(string connectionString, RaiseErrorWithNoWaitBehavior raiseErrorWithNoWaitBehavior, int? defaultCommandTimeout)
{
_connectionString = connectionString;
_raiseErrorWithNoWaitBehavior = raiseErrorWithNoWaitBehavior;
_defaultCommandTimeout = defaultCommandTimeout;
_connectionAccessor = new Lazy<SqlConnection>(() =>
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
return connection;
});
}

public IDatabaseAccessor Create()
{
SqlConnection connection = new SqlConnection(_connectionString);
SqlConnection connection = _connectionAccessor.Value;

if (_raiseErrorWithNoWaitBehavior == RaiseErrorWithNoWaitBehavior.FireInfoMessageEventOnUserErrors)
{
Expand Down Expand Up @@ -83,6 +81,12 @@ private static void OnInfoMessage(object sender, SqlInfoMessageEventArgs e)
// Unless they are of a severe exception type.
throw new AccessViolationException(exception.Message, exception);
}

void IDisposable.Dispose()
{
if (_connectionAccessor.IsValueCreated)
_connectionAccessor.Value.Dispose();
}
}

private sealed class DapperDatabaseAccessor : Dapper.DapperDatabaseAccessor
Expand Down Expand Up @@ -115,6 +119,15 @@ protected override async Task<int> ExecuteAsync(string commandText, CommandType
_ = await base.Connection.ExecuteScalarAsync(command).ConfigureAwait(false);
return default;
}

protected override void DisposeConnection()
{
// Will be disposed at the end of the test
}
}
}

internal interface IDisposableDatabaseAccessorFactory : IDatabaseAccessorFactory, IDisposable
{
}
}

0 comments on commit ce16262

Please sign in to comment.