Thargy.com

Blogs and articles by Craig Dean

Simulating SQL Server (Part 3)

If you haven’t done so so already, start with –

Simulating SQL Server (Part 1)
Simulating SQL Server (Part 2)

In the first two posts, I introduced the SqlTester library, which can be downloaded at the bottom of this post.  I also showed a series of classes that implemented IDataRecord and IDataReade to allow the creation of ‘fake’ database connections when testing code in unit tests.  For anyone who has tried messing around with compact databases (and the like) in their test projects, the resulting library can be a real time saver.

I also showed how the library could be used to quickly generate random data, using the same techniques first discussed in Generating Randomness.  That means we have the tools to create real test data and create lots of random data.  There is still one thing missing in our arsenal if we want to achieve a reasonable level of code coverage with our data layer tests.  We need to be able to simulate exceptions.

In the first post in the series, I introduced the IObjectRecord interface without comment, whilst introducing the ObjectRecord  class that implemented the interface.  It may have seemed strange that I placed an interface there, why not just use the class itself?  In the second post, I also introduced the IObjectSet , but this time, I showed two implementations – ObjectSet  and RandomSet .  The beauty of using the interfaces is it makes it easy to extend the base library yourself with further implementations.

It should come as no surprise then that I’ve included another implementation of IObjectRecord  as well – ExceptionRecord .  As the name suggests this record will throw an exception whenever it is accessed.  Unlike our other records, though, we don’t need to supply a record set definition.  Just like with a normal error we won’t be able to access any columns or data without this error being thrown anyway, so knowing the record set definition is irrelevant.

// Create an exception record (note it also implements IObjectRecord but does not require a record set definition
IObjectRecord exceptionRecord = new ExceptionRecord(new InvalidOperationException("Throw me throw a record set."));

// Add it to a new record set somewhere.
ObjectSet recordSet = new ObjectSet(recordSetDefinition)
{
    ...,
    exceptionRecord,
    ...
};

With this one class we can now ‘poison’ any record set, and make it fail exactly when we want to, and in the way we want to.

Of course, we still have a small problem here, what if we want to simulate an actual SQL Server error?  Perhaps your code (correctly) only intercepts exceptions descending from SqlException.  Unfortunately, there is no public constructor for creating a SqlException, after all, you shouldn’t normally be able to create one yourself as it’s reserved for errors coming from SQL.

Thankfully, using the power of reflection, pretty much anything is possible, so I created some prototype classes to solve this particular conundrum for you easily.  As a technique you can use this for any such similar problem, but bare in mind people make classes private for a reason, so use with caution!

// To create a record that throws an exception we first create a SqlException
// We can't do this directly, but we can use our prototypes to construct one.

// SqlExceptions are made from a collection of SqlErrors - which can make like this :
SqlErrorCollection errorCollection = new SqlErrorCollectionPrototype
    {
        new SqlErrorPrototype(1000, 80, 17, "MyFakeServer",
         "Connection Timeout.", "spMySproc", 54)
    };

SqlException sqlException = new SqlExceptionPrototype(errorCollection, "9.0.0.0", Guid.NewGuid());
IObjectRecord exceptionRecord = new ExceptionRecord(sqlException);

So how do these work?

Well basically all three prototype classes (SqlErrorPrototype , SqlErrorCollectionPrototype  and SqlExceptionPrototype ) correspond to a framework class (SqlError, SqlErrorCollection and SqlException respectively).  And all three have implicit conversion operators defined to allow conversion between the prototype class and it’s corresponding framework class.  For example, SqlErrorPrototype  contains the following code –

/// <summary>
/// Implicit conversion from <see cref="SqlErrorPrototype"/> to <see cref="SqlError"/>.
/// </summary>
/// <param name="prototype">The prototype.</param>
/// <returns>The result of the operator.</returns>
/// <remarks></remarks>
public static implicit operator SqlError(SqlErrorPrototype prototype)
{
    return prototype != null
               ? prototype.SqlError
               : null;
}

/// <summary>
/// Implicit conversion from <see cref="SqlError" /> to <see cref="SqlErrorPrototype" />.
/// </summary>
/// <param name="sqlError">The SQL error.</param>
/// <returns>The result of the operator.</returns>
/// <remarks></remarks>
public static implicit operator SqlErrorPrototype(SqlError sqlError)
{
    return sqlError != null
               ? new SqlErrorPrototype(sqlError)
               : null;
}

Because we can implicitly convert to and from the prototype, the prototype can be used anywhere the real class is needed.

If you look at the methods above, you’ll also see a reference to a public readonly  field called SqlError .  This field is actually created the moment you create an instance of the object –

/// <summary>
/// Initializes a new instance of the <see cref="SqlErrorPrototype" /> class, and in doing so initializes the <see cref="SqlError" /> property.
/// </summary>
/// <param name="infoNumber">The info number.</param>
/// <param name="errorState">State of the error.</param>
/// <param name="errorClass">The error class.</param>
/// <param name="server">The server.</param>
/// <param name="errorMessage">The error message.</param>
/// <param name="procedure">The procedure.</param>
/// <param name="lineNumber">The line number.</param>
/// <param name="win32ErrorCode">The win32 error code (if this error is the first in a <see cref="SqlException">SqlException's</see> collection then
/// this value will create an <see cref="SqlException.InnerException">inner exception</see> of type <see cref="Win32Exception"/>.</param>
/// <exception cref="System.ArgumentOutOfRangeException"></exception>
/// <remarks></remarks>
public SqlErrorPrototype(int infoNumber, byte errorState, byte errorClass = 17,
                         string server = "Unspecified server", string errorMessage = "Unspecified error",
                         string procedure = "Unspecified procedure", int lineNumber = 0, uint win32ErrorCode = 0)
    : this(
        _constructor(infoNumber, errorState, errorClass, server, errorMessage, procedure, lineNumber,
                     win32ErrorCode))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="SqlErrorPrototype" /> class.
/// </summary>
/// <param name="error">The error.</param>
/// <remarks></remarks>
public SqlErrorPrototype([NotNull] SqlError error)
{
    Contract.Assert(error != null);
    SqlError = error;
}

Looking a the highlighted lines you can see that this calls an internal method (in fact it’s a private static readonly  field of type Func<…> ) that creates our actual SqlError.  So how is this magic function created?  Well, it’s created in a static constructor, and here comes a great example of where statics are useful.  Because it’s in the static constructor it will be called once (and only once) whenever the class is first accessed – this is a cheap effective (and thread-safe) way to solve lazy initialisation.

/// <summary>
/// Creates the <see cref="_constructor"/> lambda.
/// </summary>
/// <remarks></remarks>
static SqlErrorPrototype()
{
    // Find SqlError constructor.
    ConstructorInfo constructorInfo =
        typeof (SqlError).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null,
            new[]
                {
                    typeof (int),
                    typeof (byte),
                    typeof (byte),
                    typeof (string),
                    typeof (string),
                    typeof (string),
                    typeof (int),
                    typeof (uint)
                }, null);
    Contract.Assert(constructorInfo != null);

    // Create parameters
    List<ParameterExpression> parameters = new List<ParameterExpression>(4)
                                               {
                                                   Expression.Parameter(typeof (int), "infoNumber"),
                                                   Expression.Parameter(typeof (byte), "errorState"),
                                                   Expression.Parameter(typeof (byte), "errorClass"),
                                                   Expression.Parameter(typeof (string), "server"),
                                                   Expression.Parameter(typeof (string), "errorMessage"),
                                                   Expression.Parameter(typeof (string), "procedure"),
                                                   Expression.Parameter(typeof (int), "lineNumber"),
                                                   Expression.Parameter(typeof (uint), "win32ErrorCode")
                                               };

    // Create lambda expression.
    _constructor = Expression.Lambda<Func<int, byte, byte, string, string, string, int, uint, SqlError>>(
        Expression.New(constructorInfo, parameters), parameters).Compile();
}

Using the exact same techniques we create the other two prototype classes, which of course are in the code you can download.  I shall leave an explanation of how the code above works until a later post (when I introduce a generic function for creating Action<…> s and Func<…> s) but for now be assured that calling the resultant function is as quick as calling the constructor directly (and way quicker than the appalling Activator.CreateInstance).

Finally, the ObjectReader  has a few public methods that aren’t exposed via the IDataReader interface (or the collection interface).  In the end, the ObjectReader  is a simple collection that keeps track of a single enumeration through it, unlike normal collections, where you can request multiple enumerators and enumerate them independently.  As any seasoned .NET developer will tell you, you can’t modify a collection whilst it is being enumerated.  So once you start using an ObjectReader  you can’t manipulate its contents.  To be accurate you can add/remove records to a record set other than the current one, but you can’t add/remove record sets.

To see where the ObjectReader  got up to you can use the CurrentSet  and Current  properties, which return the current set and the current record (which will be in the current set) respectively.

Unlike a real data reader, though, you can also use the Reset  method on ObjectReader  to reset the data reader back to the start (whilst keeping the data intact) so you can re-run a test (for example).

In the end, there’s a lot of functionality in the library and although I’ve covered some of the basics in these posts you can’t beat diving into the code and playing with it, so I recommend you view the code on GitHub or use the download link below to see the complete project.  All I ask is that you leave a comment or feedback, and even some suggestions if you’d like improvements.  The code is free to use in open source or commercial projects, just acknowledge it’s source.

I hope you find a use in your own tests!

Related Images:

, , , , , ,

Comments are currently closed.

5 thoughts on “Simulating SQL Server (Part 3)