views:

1740

answers:

1

How to mock ObjectContext or ObjectQuery in Entity Framework?

+7  A: 

The basic mocking frameworks can only create mocks for interfaces and for abstract classes (but only for abstract/virtual methods).

As the ObjectContext is neither abstract nor interface, it is not so easy to mock it. However, as the concrete model container is generated as partial class (if you use the designer), you can extract the methods/properties you need from it to an interface. In your code, you may use the interface only, that you can mock afterwards.

With the ObjectQuery it is a little bit more easy, as it has a base interface (e.g. IQueryable) that basically contains all the neccessary operations that you usually need (and required for LINQ). So you should expose IQueryable instead of ObjectQuery in your business logic, and you can create mock for that interface.

Other alternative is to hide all data-access related logic into a separate layer (with minimal logic), test this layer with integration tests, and mock it to be able to unit test the other layers.

There are tools (I know only TypeMock) that use the profiling hooks of .NET to generate the mocks. These tools are not limited to mock interfaces or abstract classes, but with them you can mock basically anything, including non-virtual and static methods. With such a tool you don't need to change your business logic in order to allow mocking.

Although this approach is sometimes useful, you have to be aware that extracting the dependencies to interfaces (IoC) is not only helpful for mocking, but also it reduces the dependencies between your components, that has other benefits too.

Personally I like Rhino.Mocks the best from the freeware tools, but we also use TypeMock as well, which is also a great product (but you have to pay for it).

Gaspar Nagy
Fantastic, I spent so long trying to Mock ObjectQuery but never thought to swap out ObjectQuery for IQueryable in my Repository, I literally slapped my forehead when I read this...
CodeKiwi
Yeah... just be sure that you don't go to down the IEnumerable level in abstraction, because then LINQ starts to behave differently (the queries will be executed in-memory and not by the db server).
Gaspar Nagy