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.
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.
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.
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.
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.
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.