Skip to main content

Trying to test strongly typed datatables with sqlite...

Following on from my previous post about wrapping an auto-generated strongly typed set of data-tables behind a service interface, in this post I want to show how I attempted to unit this service and failed!

The service was created for the sole purpose of abstracting away the complexity I believe an ORM would have removed (see previous post), if this functionality had been implemented by an ORM then this interface would not have existed and no testing would be required.

I was trying to perform unit testing - I wanted to test the code in isolation without any external dependencies. At this stage I didn't want to write any integration tests, since the development was deon off site and the client owned and managed the system infrastructure we believe they can take the opportunity to write integration tests after our delivery - this would allow them to prove the code base we have developed.

The system uses a Sql Server 2008 back-end - standard 2 tier stuff. So the first stage was to convert this to a Sqlite database - this would provide the database as a single file which could be included in the unit test project, thus removing the external dependency. This was easy enough using this tool hosted up on CodeProject - all done in 5 minutes.

Next stage was to modify the connection string used by the strongly typed data-tables - the client has specific requirements how this connection string was built - they inject particular connection string parameters from the app.config file. The client specific requirements wasn't the issue, the issue was the settings class containing the connection string, it was marked with sealed & internal modifiers. It was also a singleton used by all data adapters defined in the DAL.



As you can see from above no way to easily set the singleton. This wasn't difficult to get round, a bit of reflection and we have the settings class with connection string we want:

var type = Type.GetType("XXXX.RMS.DAL.My.MySettings, DAL, Version=2.0.2.0, Culture=neutral, PublicKeyToken=null");
var parameterlessCtor = (from c in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                         where c.GetParameters().Length == 0 select c).FirstOrDefault();

var instance = parameterlessCtor.Invoke(null);
var setting = (ApplicationSettingsBase) instance;
setting["XXXXConnectionString"] = "Data Source=XXXX_sqlite.db;";

I used this code in the set-up for a unit test to access the sqlite database via the strongly typed database. This is when things went wrong or more specifically my assumption was wrong - all I needed to do was change the database connection string from a Sql Server to a Sqlite version.

[Test]
public void get_package_assemblies()
{
    // Given we can manipulate the settings class and set the connection string...
    SetConnectionStringToSqlite();

    // Given we can create a assemblies table adapter...
    var adapter = new AssembliesTableAdapter();

    // When we request an assembly by id...
    var dataTable = adapter.GetByAssemblyId(13231);

    // Then we expect some results to be returned...
    Assert.IsNotNull(dataTable);
    Assert.IsNotEmpty(dataTable.Rows);
}

private void SetConnectionStringToSqlite()
{
    var type = Type.GetType("FBS.RMS.DAL.My.MySettings, DAL, Version=2.0.2.0, Culture=neutral, PublicKeyToken=null");
    var parameterlessCtor = (from c in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                                where c.GetParameters().Length == 0
                                select c).FirstOrDefault();

    var instance = parameterlessCtor.Invoke(null);
    var settings = (ApplicationSettingsBase)instance;
    settings["FBSConnectionString"] = "Data Source=FBS_sqlite.db;";

    // Set the static field - singleton used by all data table adapters...
    var tmp = settings.GetType().GetField("defaultInstance", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.SetField);
    tmp.SetValue(settings, settings);
}

The test blew at the first assert - it failed because the assumption I made about how the data adapter had been generated was wrong. I was expecting the data adapter class to have member variables for the adapter, connection & command as interfaces not as implementations of the interface, in other words instead of IConnection for the variable type it was SqlConnection.

This completely scuppered my attempt to test the service in isolation.


It's at this point I gave up trying...









Comments

Popular posts from this blog

Implementing a busy indicator using a visual overlay in MVVM

This is a technique we use at work to lock the UI whilst some long running process is happening - preventing the user clicking on stuff whilst it's retrieving or rendering data. Now we could have done this by launching a child dialog window but that feels rather out of date and clumsy, we wanted a more modern pattern similar to the way <div> overlays are done on the web. Imagine we have the following simple WPF app and when 'Click' is pressed a busy waiting overlay is shown for the duration entered into the text box. What I'm interested in here is not the actual UI element of the busy indicator but how I go about getting this to show & hide from when using MVVM. The actual UI elements are the standard Busy Indicator coming from the WPF Toolkit : The XAML behind this window is very simple, the important part is the ViewHost. As you can see the ViewHost uses a ContentPresenter element which is bound to the view model, IMainViewModel, it contains 3 child v

Showing a message box from a ViewModel in MVVM

I was doing a code review with a client last week for a WPF app using MVVM and they asked ' How can I show a message from the ViewModel? '. What follows is how I would (and have) solved the problem in the past. When I hear the words ' show a message... ' I instantly think you mean show a transient modal message box that requires the user input before continuing ' with something else ' - once the user has interacted with the message box it will disappear. The following solution only applies to this scenario. The first solution is the easiest but is very wrong from a separation perspective. It violates the ideas behind the Model-View-Controller pattern because it places View concerns inside the ViewModel - the ViewModel now knows about the type of the View and specifically it knows how to show a message box window: The second approach addresses this concern by introducing the idea of messaging\events between the ViewModel and the View. In the example below

Custom AuthorizationHandler for SignalR Hubs

How to implement IAuthorizationRequirement for SignalR in Asp.Net Core v5.0 Been battling this for a couple of days, and eventually ended up raising an issue on Asp.Net Core gitHub  to find the answer. Wanting to do some custom authorization on a SignalR Hub when the client makes a connection (Hub is created) and when an endpoint (Hub method) is called:  I was assuming I could use the same Policy for both class & method attributes, but it ain't so - not because you can't, because you need the signatures to be different. Method implementation has a resource type of HubInnovationContext: I assumed class implementation would have a resource type of HubConnectionContext - client connects etc... This isn't the case, it's infact of type DefaultHttpContext . For me I don't even need that, it can be removed completely  from the inheritence signature and override implementation. Only other thing to note, and this could be a biggy, is the ordering of the statements in th