Unit Testing ADO.NET Data Services

ADO.NET Data Services enables you to expose data (including, but not limited to, relational data) as REST services. Since it's built on top of WCF, it can be tested utilizing similar techniques, but allow me to elaborate a bit on the subject.

As with WCF, you might be interested in testing one or both tiers:

  • The service
  • The client

Testing the service is the simplest undertaking, so I'll start with that and return to testing the client in a later post.

Why would you want to unit test an ADO.NET Data Service?

The mainstream scenario for ADO.NET Data Services is to expose a relational database using an ADO.NET Entity Model. Is it relevant to unit test such a service? Perhaps not. It depends on the amount of code you inject into the generated (partial) classes. If the amount of custom code is minimal, it may not make much sense to test simple CRUD operations.

Conversely, if you have a greater degree of custom code, or if you implement an ADO.NET Data Service using non-relational data, it makes a lot of sense.

My loyal readers will probably (correctly) suspect that I would tend to expose a Façade over a Domain Model as a data service, which implies going the non-relational route (even if the underlying data store is, in fact, relational). That is also the context for the rest of this post.

First of all, you should keep in mind that the data service is just a normal class, so you can test much of its functionality by just creating it and start using it:

 [TestMethod]
 public void ServiceCanReturnRequestedItem()
 {
     // Fixture setup
     int anonymousId = 3;
     string expectedText = "Ploeh";
  
     Parent anonymousParent = new Parent();
     anonymousParent.Id = anonymousId;
     anonymousParent.Text = expectedText;
  
     MyService sut = new MyService();
     sut.ParentStore.Add(anonymousParent);
     // Exercise system
     Parent result = (from p in sut.Parents
                     where p.Id == anonymousId
                     select p).Single();
     // Verify outcome
     Assert.AreEqual<string>(expectedText, result.Text,
         "Text");
     // Teardown
 }

Notice how most of the test just contains code setting up the Fixture by adding the relevant data to the service's underlying data store, while execution and verification is quickly accomplished.

At some point, however, you will probably want to test the service through its REST interface. To do this, you must host the service within the test and then invoke it.

Hosting the service in a test is easy:

 [TestMethod]
 public void TestCanHostService()
 {
     // Fixture setup
     Uri address = new Uri("https://localhost/MyDataService");
     using (DataServiceHost host = 
         new DataServiceHost(typeof(MyDataService),
             new[] { address }))
     {
         host.Open();
         // Exercise system
         // ...
         // Verify outcome
         // ...
         // Teardown
     }
 }

Since the service is exposed through a REST interface, you can use more than one technology to invoke it. The ADO.NET Data Services client API is a natural fit, and I'll cover this in a later post. For now, just imagine that the test above contains client code that invokes the service and verifies the result.

As it turns out, unit testing an ADO.NET Data Service isn't particularly difficult. Unit testing ADO.NET Data Service Clients is a bit more involved, so I'll cover that topic in a separate post. Update: This post is now available here.

Comments

  • Anonymous
    January 14, 2009
    In my previous post , I discussed unit testing ADO.NET Data Services and how you can host and test the

  • Anonymous
    June 24, 2011
    The comment has been removed

  • Anonymous
    June 24, 2011
    If you must you the HttpContext it's best to hide it behind an interface so that you can replace it with something else for use in all those scenarios where it's not available. IIRC WCF doesn't support/populate HttpContext unless the service is running in ASP.NET Compatibility Mode, so that be something else you can try out...

  • Anonymous
    March 20, 2013
    I don't see how this actually Initializes the service so I can make calls to it. Particularly, I want to call InitializeService, but I don't know what to pass as a DataServiceConfiguration object. It would be nice to see have a working solution to look at.