Shane van Wyk
Shane van Wyk

Reputation: 1900

UnitTest FluentNhibernate using PostgreSQLConfiguration

When setting up our new architecture I followed a guide which used NHibernate with MsSql2008 configuration.

We are not using MsSql2008, instead using Postgresql. The configuration for this all works great and it saves to the database etc.

I am trying to write a unit test to test the UoW but I can't get the InMemory configuration to work.

The guide that I followed used this following Provider:

public class InMemoryNHibernateConfigurationProvider : NHibernateConfigurationProvider
{
    public override Configuration GetDatabaseConfiguration()
    {
        var databaseDriver = SQLiteConfiguration.Standard.InMemory().ShowSql();
        return CreateCoreDatabaseConfiguration(databaseDriver);
    }

    public static void InitialiseDatabase(Configuration configuration, ISession session)
    {
        new SchemaExport(configuration).Execute(true, true, false, session.Connection, Console.Out);
    }
}

My standard (Non UnitTest) configuration looks like this:

public abstract class NHibernateConfigurationProvider : INHibernateConfigurationProvider
{
    public abstract Configuration GetDatabaseConfiguration();

    public Configuration CreateCoreDatabaseConfiguration(
        IPersistenceConfigurer databaseDriver,
        Action<Configuration> databaseBuilder = null)
    {
        var fluentConfiguration =
            Fluently.Configure()
            .Database(databaseDriver)                
            .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Organisation>(new DefaultMappingConfiguration())
                //.Conventions.AddFromAssemblyOf<IdGenerationConvention>()
                 .UseOverridesFromAssemblyOf<OrganisationMappingOverride>()));

        if (databaseBuilder != null)
        {
            fluentConfiguration.ExposeConfiguration(databaseBuilder);
        }

        return fluentConfiguration.BuildConfiguration();
    }
}


public class PostgreSQLServerNHibernateConfigurationProvider : NHibernateConfigurationProvider
{
    private static readonly string NpgsqlConnectionString = ConfigurationManager.ConnectionStrings["ProdDBConnection"].ConnectionString;

    public override Configuration GetDatabaseConfiguration()
    {
        return CreateCoreDatabaseConfiguration(
            PostgreSQLConfiguration.Standard.ConnectionString(NpgsqlConnectionString).
                Dialect("NHibernate.Dialect.PostgreSQL82Dialect").ShowSql(),
            BuildDatabase);
    }

    ....... // Other Methods etc
}

How do I write a InMemoryConfigurationProvider that tests using PostgresqlConfiguration instead of SqlLiteCOnfiguration. PostgresqlConfiguration does not have an InMemory option.

Do I implement a configuration that creates another database and just drop it on teardown? Or is there perhaps another way of doing it?

Upvotes: 0

Views: 259

Answers (1)

aeliusd
aeliusd

Reputation: 469

Using sqlite works really well and although it does have some differences to SQL-server which we use they are so minor it doesn't matter for testing purposes. With that said, this is how we setup the tests: All test-cases where we want to write/read from db extend the SqLiteTestBaseclass. That way they all get access to a session created by the basesetup method, and can setup the daos / repositories as needed. Using this approach we also always get a fresh new db for each test-case.

Update: After trying this out a bit more I actually found that you have to modify it a bit to use InMemory (we had previously used sqlite backed by a file on disk instead). So the updated (complete) setup looks like this:

private Configuration _savedConfig;

[SetUp]
public void BaseSetup()
{

    FluentConfiguration configuration =
                    Fluently.Configure()

                        .Database(SQLiteConfiguration.Standard
                                            .InMemory)
                        .ExposeConfiguration(
                            x => x.SetInterceptor(new MultiTenancyInterceptor(ff)))
                        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>())
                        .Mappings(m => m.FluentMappings.ExportTo("c:\\temp\\mapping"))
                        .ExposeConfiguration(x => _savedConfig = x) //save the nhibernate configuration for use when creating the schema, in order to be able to use the same connection
                        .ExposeConfiguration(x => ConfigureEnvers(x))
                        .ExposeConfiguration(x => ConfigureListeners(x));

    ISessionFactory sessionFactory;
    try
    {
        sessionFactory = configuration.BuildSessionFactory();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.StackTrace);
        throw;
    }
    _session = sessionFactory.OpenSession();

    BuildSchema(_savedConfig, _session);
}

private void BuildSchema(Configuration config, ISession session)
{
    new SchemaExport(config)
     .Execute(false, true, false, session.Connection, null);
}

The reason why you have to jump through all these hoops in order to use the in-memory version of Sqlite is due to the db being tied to the connection. You have to use the same connection that creates the db to populate the schema, thus we have to save the Configuration object so that we can export the schema later when we've created the connection.

See this blogpost for some more details: http://www.tigraine.at/2009/05/29/fluent-nhibernate-gotchas-when-testing-with-an-in-memory-database/

N.B: This only shows the setup of the db. We have some code which also populates the db with standard values (users, customers, masterdata etc) but I've omitted that for brevity.

Upvotes: 1

Related Questions