Creating a testable WCF RIA Domain Service – Part 2


I posted a few weeks ago about writing a testable LinqToEntities domain service and came up with a number of options. The last one was my preferred choice i.e. use of the new keyword to “overwrite” the real context on the base class with an interface that your context implements. I’ve now refined it to create a very simple class that I call the MockableDomainService.

Here’s how it works: –

1. Create a mockable EF object context

This has been covered in many places on the net so I won’t bore you with the details; instead I’ll point you here again and show a class diagram of how your mocked context might look:

image

2. Copy the code for MockableDomainService

MockableDomainService inherits from LinqToEntitiesDomainService, but unlike that service class, this one is not as closely coupled to your ObjectContext. Instead it has two generic parameters – the ObjectContext (in our example, BusinessContext) and the testable interface that it implements (IBusinessContext).

You can download the code here, but here’s the code (I’m pasting the code as a screenshot since I still can’t figure out how to gracefully paste code into WordPress with Windows Live Writer…)

image

3. Inherit from MockableDomainService

Now take your real domain service, and inherit from MockableDomainService instead of the LinqToEntitiesDomainService. In your production code, simply create it with the default constructor. When you want to test your domain service, create it passing in your Fake object context instead. All your Domain Service queries will now execute against that instead – job done!

There’s still things that need work on this mockable domain service – you’ll still need to get it to handle change sets and the like – basically all the other stuff that LinqToEntities domain service gives you – but for getting going and at least testing out your queries, this should work just fine.

Testing out the Entity Framework WCF RIA Services Domain Service


I’ve started using RIA Services lately and have been testing it out with an EF4 back-end. Generally I’m quite impressed with it, as it gives you several things out of the box that you normally would need to spend time coding otherwise: –

  • Hosting of the WCF service
  • IQueryable on the client
  • Batch updates through the client-side domain context
  • Change change of client-side entities
  • Change notification of client-side entities

The last two are particularly nice as they mean that you don’t have to do this work on your server-side domain model – RIA services automatically code gens up client-side types that do this automatically.

On the server side, you have a domain service which is essentially just a class that inherits from DomainService, which in turn acts as a smart WCF service, doing a lot of the work of hosting the service etc. for you for free. However, if you’re using EF4, you can inherit from LinqToEntitiesDomainService<TObjectContext>, which gives you some more things out of the box that you would normally have to code up for your domain service. This includes a property called ObjectContext which is the context used for accessing your data store.

Testing out your domain service

Unfortunately, the above EF Domain Service couples itself to the concrete object context, and so thus rules out testing your domain service or the queries that you execute in that service. I looked around and found precious few examples on how to test out a LinqToEntities Domain Service. There’s an example for testing out a LinqToSql service, but that’s it. So, here are a few options I came up with to allow you to test out your Entity Framework Domain Service.

Use the standard Domain Service

Here, you simply use the standard domain service rather than the EF one, which gives you the ability to inject your ObjectContext as you see fit.

Create a “regular” domain service, and reference an interface to your object context (lets call it IObjectContext) rather than a concrete object context (I suggest looking here for details on how to use IObjectSet as a way to mock the object context). You can inject the context manually or use an IoC framework to do it for you. Then, you write queries to your data source through the IObjectContext etc.

image

This solution functions, but you will lose any extra features that the LinqToEntitiesDomainService gives you – I’ll blog about this in the future.

Use the repository pattern to test your queries

In this example, your use the real EF Domain Service, but instead of writing queries directly in your service, you create a Repository class which takes in an IObjectContext and executes its queries there. You can test out your repository queries in the normal manner i.e. in your unit tests, create a fake ObjectContext and supply that to your repository class.

image

However, your cannot test out any of your domain service “business logic” code in MyService as this is still tightly coupled to the concrete ObjectContext. Only your queries against the context can be tested.

Put your real logic in a delegated class

Here, you create a class which will have the same method signatures as your domain service, and your domain service delegates all calls to it. Your domain service is a “proper” EF Domain Service, so you get all the benefits of lifecycle management etc. of the context, but still have the ability to fake out the context to make your code testable. In effect, your Domain Service becomes a proxy for the real business logic.

Create an interface for your Domain Service which has all the methods that you’re going to expose. Then, create another class which implements that interface and contains all your business logic and queries in. In essence, this is the “real” domain service, except it doesn’t inherit from Domain Service etc.. In your Domain Service class, you create an instance of this “delegated” service, passing in the concrete object context, and delegate all calls to it. Because the “delegated” service class is only coupled to IObjectContext, you can full test it out, yet you get the benefits of EFDomainService because that class is still created.

image

However, this is possible the most complicated of all the different ways of abstracting away the context, and you have a somewhat ugly manual delegation of calls going on – and for every new domain method you create, you need to update the interface etc., so it’s a bit of work.

Shim in a fake context

In this scenario, you simply create a new property on your EF Domain Service which overrides and thus hides the “real” Object Context. The new property is the interface; all access to the context goes via this property rather than the base ObjectContext.

image

With this fairly lightweight approach, you create a property with the same name as the “real” context that exists on the base class, ObjectContext, and use the new keyword to override it. You then use constructor-based injection to use a fake context when required; otherwise you use the base ObjectContext.

image

With this approach, as long as you remember to never use base.ObjectContext, you can effectively shim in a fake context without any need for proxies or repository classes; your service is still fully testable and you get all the goodness of the LinqToEntities Domain Service.