Back in July, I posted an article on how to mock out the database in ActiveRecord. The approach is simple, but is not mocking in the strict sense. I use SQLite in "memory" mode, creating a temporal database for testing. My colleague, Jay Harris, has updated my code to allow for configuration in two ways. He has preserved my "drop-in" mode via the "useDynamicConfiguration" flag but when the flag is false, you can use a configuration from the app.config file.
Here is the newest version of the code:
using System;
using System.Collections;
using System.Data;
using System.Reflection;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
using Castle.ActiveRecord.Framework.Config;
using NHibernate.Connection;
namespace ActiveRecordTestHelper
{
public class ActiveRecordMockConnectionProvider : DriverConnectionProvider
{
private static IDbConnection _connection;
private static IConfigurationSource MockConfiguration
{
get
{
var properties = new Hashtable
{
{"hibernate.connection.driver_class",
"NHibernate.Driver.SQLite20Driver"},
{"hibernate.dialect", "NHibernate.Dialect.SQLiteDialect"},
{"hibernate.connection.provider", ConnectionProviderLocator},
{"hibernate.connection.connection_string",
"Data Source=:memory:;Version=3;New=True;"}
};
var source = new InPlaceConfigurationSource();
source.Add(typeof (ActiveRecordBase), properties);
return source;
}
}
private static string ConnectionProviderLocator
{
get { return String.Format("{0}, {1}", TypeOfEnclosingClass.FullName,
EnclosingAssemblyName.Split(',')[0]); }
}
private static Type TypeOfEnclosingClass
{
get { return MethodBase.GetCurrentMethod().DeclaringType; }
}
private static string EnclosingAssemblyName
{
get { return Assembly.GetAssembly(TypeOfEnclosingClass).FullName; }
}
public override IDbConnection GetConnection()
{
if (_connection == null)
_connection = base.GetConnection();
return _connection;
}
public override void CloseConnection(IDbConnection conn) {}
/// <summary>
/// Destroys the connection that is kept open in order to keep the
/// in-memory database alive. Destroying the connection will destroy
/// all of the data stored in the mock database. Call this method when
/// the test is complete.
/// </summary>
public static void ExplicitlyDestroyConnection()
{
if (_connection != null)
{
_connection.Close();
_connection = null;
}
}
/// <summary>
/// Initializes ActiveRecord and the Database that ActiveRecord uses to
/// store the data. Call this method before the test executes.
/// </summary>
/// <param name="useDynamicConfiguration">
/// Use reflection to build configuration, rather than the Configuration
/// file.
/// </param>
/// <param name="types">
/// A list of ActiveRecord types that will be created in the database
/// </param>
public static void InitializeActiveRecord(bool useDynamicConfiguration,
params Type[] types)
{
ActiveRecordStarter.ResetInitializationFlag();
IConfigurationSource configurationSource = useDynamicConfiguration
? MockConfiguration
: ActiveRecordSectionHandler.Instance;
ActiveRecordStarter.Initialize(configurationSource, types);
ActiveRecordStarter.CreateSchema();
}
/// <summary>
/// Initializes ActiveRecord and the Database that ActiveRecord uses to
/// store the data based. Configuration is dynamically generated using
/// reflection. Call this method before the test executes.
/// </summary>
/// <param name="types">
/// A list of ActiveRecord types that will be created in the database
/// </param>
[Obsolete("Use InitializeActiveRecord(bool, params Type[])")]
public static void InitializeActiveRecord(params Type[] types)
{
InitializeActiveRecord(true, types);
}
}
}
It can be downloaded from Jay's site: ActiveRecordMockConfigurationProvider.zip