Wednesday, February 03, 2010

Mocking Entity Framework ObjectSets

After finally getting my head around object-graph deletes in Entity Framework v4, I set about getting some better testing around my EF code.  The first step was updating my self-tracking entities template to have my object-sets be exposed as IObjectSets which involved a small tweak to my TT file.

I ran into some challenges using a Rhino Mock of IObjectSet, so I let Google do some work for me and I landed on Jamie Phillip’s post about mocking IObjectSet via his MockObjectSet., which was exactly what I was looking for.  Adding this class into my test library got me 90% of where I wanted to be, but I still had compile errors on the spots where I was building out my object-graphs with “.Include(“”)” calls. 

After some time digging through the EF4 code with Reflector,  I was not finding what I thought I needed, an IObjectQuery interface, which would allow me to mock the Include method.  Again, I went back to Google and ran across a MSDN Forum post which Diego Vega answered with an almost too obvious solution to my exact problem: use an extension-method for Include.

Since I was only interested in mocking out the “Include” behavior, and have my MockOjectSet return my configured entity list, I went with Diego’s first suggestion for Include, which looks like this:

public static IQueryable<T> Include<T>(this IQueryable<T> source, string path){
   var objectQuery = source as ObjectQuery<T>;
   if (objectQuery != null){
      return objectQuery.Include(path);
   }
   return source;
}

The only pain point to this approach to testing, is that I’m stuck remembering that I need to add a new extension method whenever I utilize one of the methods in the ObjectQuery<T> class – Union, Distinct, etc.

2 comments:

  1. Hi Tony,

    Nice blog, and glad to hear that the Include extension method helped! One clarification about other extension methods: IObjectSet is an IQueryable, so most existing standard LINQ query operators (including Union and Distinct) should work with both the real ObjectSet and with the fake ObjectSet. So you shouldn’t need to write them again. Include is special because it exists only in ObjectQuery but there is no extension method for IQueryable in the .NET Framework (so far). Of course there are some subtle differences in the behaviors of some operators between LINQ to Objects and LINQ to Entities (and LINQ to Entities supports only a subset of them), but the point of creating fakes at the IObjectSet level is to take advantage of the similarities to write less code when defining your repositories. I recommend that you run your unit tests against the actual backend once in a while to make sure there are no subtle bugs that you are missing because of those differences.

    By the way, besides Jamie’s post, there are have been a few more published about this. Here you can find a series by Julie Lerman:
    http://thedatafarm.com/blog/data-access/agile-entity-framework-4-repository-part-5-iobjectset/

    And here is one my colleague Jonathan Aneja published in the ADO.NET Team blog:
    http://blogs.msdn.com/adonet/pages/walkthrough-test-driven-development-with-the-entity-framework-4-0.aspx

    Hope this helps,
    Diego

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete