Getting the Entity Framework to Generate an Interface for Mocking

Posted: August 8, 2010 in ADO.NET Entity Framework
Tags: , , , , ,

Whilst playing with the Entity Framework, I though it would be pretty cool if the auto generated code would create and implement an interface along with the standard data context and entity classes. This would make unit testing with a mocking framework really easy, and allow you to write tests without having to access a data access store. Usually I write a wrapping repository to mock out, but this is a little tiresome. Since the Entity Framework is really flexible, this shouldn’t be too much trouble. So lets give it a bash.

I used the POCO class T4 templates as a basis. You can read more about them here. I am no T4 expert, but the code is intuitive enough to make sense of it, and more importantly to make some modifications to it.

Making the Changes

We first create a new class library project and create a folder for our EDMX and supporting classes in the repo.

01-New Project

After this we create a standard EDMX

02-Add New EDMX

I am going to play with a basic invoicing model

03-Model

I am also going to be doing this in design first mode, but it is no different if you are generating off an existing database. If we take a look at the generated code behind we can see a couple of things.

04-Designer Code

We see that our container inherits from the ObjectContext base class, we also see that outside of this class is a region for all the generated entities. These entities by default derive from the EntityObject class. The objective of the POCO T4 template is to decouple this using dynamic proxies and some black voodoo magic. Also if we take a look at the properties for the ObjectContext we notice that the Code Generation Strategy is set to Default.

05-Code Generation Strategy

What we are going to do next is to tell the EDMX to use our own custom code generation strategy. Right clicking on the design surface, we select “Add Code Generation Item..” from the context menu.

06-Add Code Generation Item

If you have installed the POCO generator extension then you will see it in the dialog box. Select this.

07-POCO Entity Generator

What this does is adds two T4 templates to the project, one for generating the new ObjectContext and the other for generating the entities. These .TT files have the generated code behind .CS files. You can explore them as well as the template that generated them. To help in viewing the T4 template I recommend downloading a copy of Tangible T4 Editor, this gives you some nice highlighting and some intellisense on the T4 template code.

08-Template Files

Next, we need to copy the .Context.TT file and paste it in the folder, this will give us a file to work with for the interface. Rename it to something more appropriate like “Context.Interface.tt”. We now dive into this new file and make some changes so that it generates an interface off the EDMX file.

10-Interface Definition

We create a prefix an “I” onto the container name, and implement the IDisposable interface onto the interface. Also make sure to change “class” to interface. We then remove all the unnecessary stuff like the constructor definitions.

11- Property Definition

For the property definitions we change them to a return type of IObjectSet. This is so we can mock out the return types for any LinQ / Lambda queries against the interface. Also make sure we only implement the GET portion of the property. Also get rid of all the implementation stuff around the property so that only the definition is left.

Onto the function imports. We do a similar thing, reduce to definitions and remove the implementation stuff.

12-Function Imports

For the VB.Net version of the POCO class generator there is a bug in the function import code, I blogged on this here. You will have to code around this. To be fair, I haven’t tested the ObjectResult return type, but if you cant instantiate it then you will have to do something similar to the properties and find an appropriate interface to substitute.

13-Generated Interface

If all goes well, on saving the template we get a nice clean interface generated against our context entities.

We also need to add some of the functionality found in the ObjectContext, like SaveChanges, etc. So it may be invoked through the interface. Add what you need.

18-Additional Context Methods

The next task is now modifying the generator for the ObjectContext so that it implements our interface.

14-Context Implementing Interface

We do this by modifying the definition of the ObjectContext to implement the interface.

We also change the property definition to return IObjectset. Also note for VB.Net, since you need to implement interfaces explicitly, you will also need to add this on the end of the property.

15-Properties Implement IObjectset

We can now inspect the new generated ObjectContext.

16-New Generated Context

Testing it Out

Lets write some implementation code to test. Typically one write some form of service that implements the data context. We also want to unit test the service by mocking out the repository.

Lets create a basic service.

17-Create Service

Some things to note here. We use a constructor dependency injection pattern here to allow us to inject our own flavor of repository. Also we have a method called “CreateInvoice” that receives some information (via a front end or wherever) and creates the header and associative entities for an invoice. You should be able to eyeball the implementation.

We now need a little helper class that implements the IObjectSet interface so we can return it. We also dont want it to be completely dumb as it would be nice if we could base our assertions off this object to verify the integrity of the data the service method is producing. So we base it off a List class. This was pulled off MSDN

19-Fake Obkect Set

We call this FakeObjectSet appropriately. Notice it is a generic.

We also add Rhino Mocks as our mocking framework.

20- Add Rhino Mocks

We then create a fancy mocking test to verify the behaviour of the service method. I am not going to worry about philosophies of mocking vs. stubbing here. This is just an example of a test.

21- Create fancy mock test

Some interesting points here are:

We use the generate our FakeObjectSets with fake data relevant to the test.

We use the mocking framework to return this data to the service.

The Repo is mocked.

We can query the repo after the fact to verify the data in it. We compare this to our input data to ensure all business rules have been applied.

We then run the test.

22- Verify Results

Green lights baby…green lights.

For getting started with the Entity Framework follow my multi part tutorial

Advertisements
Comments
  1. scottcate says:

    Great Work! Thank you! I’ll put this into my bag of EF knowledge.

  2. […] showing how to use the IDbSet interface to create unit tests. (example here or an older example here) Be warned: that is only half the story and the blogs are quiet on anything else. Once you take […]

  3. Olena says:

    Thank you so much for the article, I have followed your steps and it worked! The only difference is that I used Moq library for testing.

  4. […] followed the instructions from Slappy’s Blog which covered most of the […]

  5. You can copy my T4 files to generate interfaces for EF types. And then you can test them out.

    https://entityinterfacegenerator.codeplex.com/

    Extract interfaces for DbContext and entity classes. (version 1.0.0.0)
    Add same attributes to entity classes and interfaces. (version 1.1.0.0)

    My upcoming releases will have escape the Data Access Layer and go to Business Layer very soon:

    Add different attributes to entity classes and interfaces targeted by type names.
    Add different attributes to entity classes and interfaces targeted by type’s properties.

    Generate generic repository interfaces for CRUD.
    Generate generic repository interfaces for Direct References.
    Generate generic repository interfaces for Indirect References.

    Generate mocks and stubs for faking DbContext.
    Generate unit tests to test database compatibility.
    Generate unit test to test imported functions.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s