Skip to content

Commit

Permalink
BREAKING: Require Persistence model generator as constructor paramete…
Browse files Browse the repository at this point in the history
…r for TestDatabaseSetup (#259)

Closes #248

+semver:major
  • Loading branch information
cd21h committed Oct 26, 2021
1 parent b90d11f commit 312b78f
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Suteki.TardisBank.Tasks
public interface IUserService
{
Task<User?> GetCurrentUser(CancellationToken cancellationToken = default);
Task<User> GetUser(int userId, CancellationToken cancellationToken = default);
Task<User?> GetUser(int userId, CancellationToken cancellationToken = default);
Task<User?> GetUserByUserName(string userName, CancellationToken cancellationToken = default);
Task<User?> GetUserByActivationKey(string activationKey, CancellationToken cancellationToken = default);
Task SaveUser(User user, CancellationToken cancellationToken = default);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public UserService(IHttpContextService context, ILinqRepository<Parent, int> par
return GetUserByUserName(_context.UserName, cancellationToken);
}

public Task<User> GetUser(int userId, CancellationToken cancellationToken)
public Task<User?> GetUser(int userId, CancellationToken cancellationToken)
{
return _userRepository.FindOneAsync(userId, cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class TransientDatabaseSetup : TestDatabaseSetup
{
/// <inheritdoc />
public TransientDatabaseSetup()
: base(typeof(TransientDatabaseSetup).Assembly, new[]
: base(typeof(TransientDatabaseSetup).Assembly, typeof(AutoPersistenceModelGenerator), new[]
{
typeof(AutoPersistenceModelGenerator).Assembly
})
Expand Down
1 change: 1 addition & 0 deletions SharpArch.AutoLoad.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ FluentAssertions.AssertionExtensions.Should($EXPR$).NotBeNull()&#xD;
<s:Boolean x:Key="/Default/UserDictionary/Words/=sqlite/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Suteki/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tardis/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xunit/@EntryIndexedValue">True</s:Boolean>


</wpf:ResourceDictionary>
124 changes: 54 additions & 70 deletions Src/Common/NHibernate/TestDatabaseSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,59 @@ public class TestDatabaseSetup : IDisposable
{
readonly string _basePath;
readonly Assembly[] _mappingAssemblies;
readonly Type _persistenceModelGenerator;
Configuration? _configuration;
ISessionFactory? _sessionFactory;

/// <summary>
/// Allows to apply custom configuration to new ISession.
/// </summary>
/// <remarks>
/// Callback is executed by default implementation of <see cref="ConfigureSession" /> from <see cref="InitializeSession" />.
/// </remarks>
public Action<ISessionBuilder>? SessionConfigurator { get; set; }

/// <summary>
/// Allows to apply custom configuration to new ISession.
/// </summary>
/// <remarks>
/// Callback is executed by default implementation of <see cref="ConfigureSession" /> from <see cref="InitializeSession" />.
/// </remarks>
public Action<IStatelessSessionBuilder>? StatelessSessionConfigurator { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="TestDatabaseSetup" /> class.
/// </summary>
/// <param name="basePath">Base bath to use when looking for mapping assemblies and default NHibernate configuration file.</param>
/// <param name="persistenceModelGenerator">Persistence model generator, type. Must implement <see cref="IAutoPersistenceModelGenerator" />.</param>
/// <param name="mappingAssemblies">
/// List of assemblies containing NHibernate mapping files and persistence model generator.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="basePath" /> or <paramref name="mappingAssemblies" /> is
/// <paramref name="basePath" />, <paramref name="persistenceModelGenerator" /> or <paramref name="mappingAssemblies" /> is
/// <c>null</c>.
/// </exception>
public TestDatabaseSetup(string basePath, Assembly[] mappingAssemblies)
/// <exception cref="ArgumentException">
/// <paramref name="persistenceModelGenerator" /> does not implement <see cref="IAutoPersistenceModelGenerator" />.
/// </exception>
public TestDatabaseSetup(
string basePath,
Type persistenceModelGenerator,
Assembly[] mappingAssemblies)
{
_basePath = basePath ?? throw new ArgumentNullException(nameof(basePath));
_persistenceModelGenerator = persistenceModelGenerator ?? throw new ArgumentNullException(nameof(persistenceModelGenerator));
if (!typeof(IAutoPersistenceModelGenerator).IsAssignableFrom(persistenceModelGenerator))
throw new ArgumentException($"Type {persistenceModelGenerator.FullName} must implement {nameof(IAutoPersistenceModelGenerator)}.");

if (mappingAssemblies == null) throw new ArgumentNullException(nameof(mappingAssemblies));
_mappingAssemblies = mappingAssemblies.Distinct().ToArray();
}

/// <summary>
/// Initializes a new instance of the <see cref="TestDatabaseSetup" /> class.
/// </summary>
/// <param name="persistenceModelGenerator">Persistence model generator, type. Must implement <see cref="IAutoPersistenceModelGenerator" />.</param>
/// <param name="baseAssembly">
/// Assembly to use to determine configuration folder. Typically is it assembly containing
/// tests.
Expand All @@ -61,28 +90,19 @@ public TestDatabaseSetup(string basePath, Assembly[] mappingAssemblies)
/// <paramref name="baseAssembly" /> or <paramref name="mappingAssemblies" /> is
/// <c>null</c>.
/// </exception>
public TestDatabaseSetup(Assembly baseAssembly, Assembly[] mappingAssemblies)
/// <exception cref="ArgumentException">
/// <paramref name="persistenceModelGenerator" /> does not implement <see cref="IAutoPersistenceModelGenerator" />.
/// </exception>
public TestDatabaseSetup(
Assembly baseAssembly,
Type persistenceModelGenerator,
Assembly[] mappingAssemblies)
: this(CodeBaseLocator.GetAssemblyCodeBasePath(baseAssembly),
persistenceModelGenerator,
mappingAssemblies)
{
}

/// <summary>
/// Allows to apply custom configuration to new ISession.
/// </summary>
/// <remarks>
/// Callback is executed by default implementation of <see cref="ConfigureSession" /> from <see cref="InitializeSession" />.
/// </remarks>
public Action<ISessionBuilder>? SessionConfigurator { get; set; }

/// <summary>
/// Allows to apply custom configuration to new ISession.
/// </summary>
/// <remarks>
/// Callback is executed by default implementation of <see cref="ConfigureSession" /> from <see cref="InitializeSession" />.
/// </remarks>
public Action<IStatelessSessionBuilder>? StatelessSessionConfigurator { get; set; }

/// <summary>
/// Disposes SessionFactory.
/// </summary>
Expand All @@ -94,64 +114,15 @@ public virtual void Dispose()
GC.SuppressFinalize(this);
}

/// <summary>
/// Generates auto-persistence model.
/// </summary>
/// <param name="assemblies">List of assemblies to look for auto-persistence model generators.</param>
/// <returns>
/// <see cref="AutoPersistenceModel" />
/// </returns>
/// <remarks>
/// This method will load and scan assemblies for <see cref="IAutoPersistenceModelGenerator" />.
/// Only first generated model is returned.
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="assemblies" /> is <see langword="null" /></exception>
/// <exception cref="InvalidOperationException">
/// Only one implementation of <see cref="IAutoPersistenceModelGenerator" /> is
/// allowed.
/// </exception>
/// <exception cref="TargetInvocationException">Unable to instantiate AutoPersistenceModelGenerator.</exception>

public static AutoPersistenceModel GenerateAutoPersistenceModel(Assembly[] assemblies)
{
if (assemblies == null) throw new ArgumentNullException(nameof(assemblies));
var persistenceGeneratorTypes = assemblies.SelectMany(a =>
a.GetTypes().Where(t =>
!t.IsAbstract && typeof(IAutoPersistenceModelGenerator).IsAssignableFrom(t)))
.ToArray();
if (persistenceGeneratorTypes.Length > 1)
throw new InvalidOperationException($"Found multiple classes implementing {nameof(IAutoPersistenceModelGenerator)}. " +
"Only one persistence model generator is supported.")
{
Data =
{
[nameof(IAutoPersistenceModelGenerator) + "s"] = persistenceGeneratorTypes,
["Assemblies"] = assemblies
}
};
if (persistenceGeneratorTypes.Length == 0)
throw new InvalidOperationException($"No classes implementing {nameof(IAutoPersistenceModelGenerator)} were found. " +
$"{nameof(TestDatabaseSetup)} requires persistence model generator to create test database.")
{
Data =
{
["Assemblies"] = assemblies
}
};
var generator = (IAutoPersistenceModelGenerator) Activator.CreateInstance(persistenceGeneratorTypes[0])!;
return generator.Generate();
}

/// <summary>
/// Returns NHibernate <see cref="Configuration" />.
/// Configuration instance is cached, all subsequent calls will return the same instance.
/// </summary>

public Configuration GetConfiguration()
{
if (_configuration != null) return _configuration;

var autoPersistenceModel = GenerateAutoPersistenceModel(_mappingAssemblies);
var autoPersistenceModel = GenerateAutoPersistenceModel();

var builder = new NHibernateSessionFactoryBuilder()
.AddMappingAssemblies(_mappingAssemblies)
Expand All @@ -171,6 +142,19 @@ public Configuration GetConfiguration()
return _configuration;
}

/// <summary>
/// Generates auto-persistence model.
/// </summary>
/// <returns>
/// <see cref="AutoPersistenceModel" />
/// </returns>
/// <exception cref="TargetInvocationException">Unable to instantiate AutoPersistenceModelGenerator.</exception>
public AutoPersistenceModel GenerateAutoPersistenceModel()
{
var generator = (IAutoPersistenceModelGenerator)Activator.CreateInstance(_persistenceModelGenerator)!;
return generator.Generate();
}

/// <summary>
/// Override this method to customize NHibernate configuration.
/// </summary>
Expand Down Expand Up @@ -256,7 +240,7 @@ public static void Close(ISession? session)
/// </summary>
/// <param name="sessionFactory">The session factory.</param>
/// <remarks>
/// Dispose <see cref="TestDatabaseSetup" /> will destroy Session Factory associated with this instance.
/// Disposing <see cref="TestDatabaseSetup" /> will destroy Session Factory associated with this instance.
/// </remarks>
public static void Shutdown(ISessionFactory? sessionFactory)
=> sessionFactory?.Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using global::NUnit.Framework;
using JetBrains.Annotations;
using SharpArch.NHibernate;
using SharpArch.NHibernate.FluentNHibernate;
using Testing.NHibernate;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using global::NHibernate;
using global::Xunit;
using JetBrains.Annotations;
using SharpArch.NHibernate.FluentNHibernate;
using SharpArch.Testing.NHibernate;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/// such as a SQL Server instance, then use <see cref="LiveDatabaseTests{TDatabaseInitializer}" /> instead.
/// </para>
/// </summary>
/// <typeparam name="TDatabaseSetup">Database setup class.</typeparam>
[PublicAPI]
public abstract class TransientDatabaseTests<TDatabaseSetup> : IClassFixture<TDatabaseSetup>, IDisposable, IAsyncLifetime
where TDatabaseSetup : TestDatabaseSetup, new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class HasUniqueDomainSignatureTestsBase : RepositoryTestsBase

public HasUniqueDomainSignatureTestsBase()
: base(new TestDatabaseSetup(
TestContext.CurrentContext.TestDirectory, new[] {typeof(TestsPersistenceModelGenerator).Assembly}
TestContext.CurrentContext.TestDirectory,
typeof(TestsPersistenceModelGenerator),
new[] {typeof(TestsPersistenceModelGenerator).Assembly}
))
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using global::SharpArch.Domain.PersistenceSupport;
using global::SharpArch.NHibernate;
using global::SharpArch.Testing.Xunit.NHibernate;
using Mappings;
using Moq;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using FluentAssertions;
using global::SharpArch.NHibernate;
using global::SharpArch.Testing.Xunit.NHibernate;
using Mappings;
using Xunit;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ public class NHibernateTestsSetup : TestDatabaseSetup
{
public NHibernateTestsSetup()
: base(Assembly.GetExecutingAssembly().Location,
typeof(TestsPersistenceModelGenerator),
new[]
{
typeof(ObjectWithGuidId).Assembly,
typeof(TestsPersistenceModelGenerator).Assembly
//typeof(TestsPersistenceModelGenerator).Assembly
})
{
}
Expand All @@ -27,7 +28,7 @@ protected override void Customize(NHibernateSessionFactoryBuilder builder)
{
base.Customize(builder);
builder.UsePersistenceConfigurer(new SQLiteConfiguration().InMemory());
builder.UseProperties(new SortedList<string, string>()
builder.UseProperties(new SortedList<string, string>
{
[Environment.ReleaseConnections] = "on_close",
[Environment.Hbm2ddlAuto] = "create"
Expand Down

0 comments on commit 312b78f

Please sign in to comment.