Update for the ActiveRecord "Mock" Framework

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

Leave a Reply