Can it be done without using TypeMock Islolator? I've found a few suggestions online such as passing in a metadata only connection string, however nothing I've come across besides TypeMock seems to truly allow for a mock ObjectContext that can be injected into services for unit testing. Do I plunk down the $$ for TypeMock, or are there alternatives? Has nobody managed to create anything comparable to TypeMock that is open source?
I'm unit testing EF4 easily without mocking. What I did was create a repository interface using the code from http://elegantcode.com/2009/12/15/entity-framework-ef4-generic-repository-and-unit-of-work-prototype/ as a basis I then created an InMemoryRepository<T> class that used the IRepository interface. I then replaced the IObjectSet<T> with a List<T> inside of the class and changed the retrieval methods accordingly.
Thus if you need to do unit testing, pass in the InMemoryRepository rather than the DataRepository.
Put your Linq2Entity query behind an interface, unit test it in isolation against a real database.
Write tests for your business logic with mocks for your query interfaces. Don't let Linq bleed into your business logic!
Don't use the RepositoryPattern!
Wrap the ObjectContext in a proxy class. Then inject that into your classes.
I don't think the repository pattern is the only answer to the question (it avoids the problem, sure)
I liked this answer - I think more appropriate for introducing tests to an existing codebase Creating Interface for ObjectContext
Related
I have read lots of SO links about unit/integration testing of the entity framework and to sum it all up if I have not misunderstood:
When the repository interface exposes an IQueryable I have to do integration tests (unit tests are not sufficient) because the IQueryable which is linq to entities can be turned into a linq to objects query which can behave totally different which can only be tested having a real database.
When the repository interface exposes only IEnumerable or List it is enough to unit test the repository.
I know it can be very cool to compose an IQueryable in my service without adding many new interface methods...
But if the above is true and I want to avoid integration tests if possible...
What do you think?
When the repository interface exposes only IEnumerable or List it is
enough to unit test the repository.
No. That is misunderstanding. When repository exposes only IEnumerable or List it is safe to fake or mock it and unit test the logic using your repository. The repository itself must be still covered with integration tests because it defines database queries which must be tested against the real database.
The main reason to hide the query behind the repository is to separate concerns and define strict boundary between application logic and database executed logic (the query). Each logic requires its own tests.
Questions you are referring most probably discussed mocking or faking the EF context / EF sets or repository exposing IQueryable. In such case the repository exposes database executed logic into upper layer which makes correct testing much harder. In such case you need to unit test your application logic and somehow fake Linq-to-entities (database logic) with Linq-to-objects. But such tests are not enough to test those queries so you also need integration tests which will duplicate part of your unit tests.
In my project, I need to use EF and abstract the queries from the Presentation layer. Based from what I've been reading questions and answers all over the net, EF is built having repository pattern on it's DbSet and Unit of work on DbContext.
Repository pattern can easily do the requirement but I don't wanna repeat this implementation and now confused where should I initialize or access the DbContext. Should it be on the service layer?
MVC4 Api will be used for this project
One way I have seen this done in the past is to essentially remove the DbContext's dependency on a physical database by creating an interface for your context then make your data access calls from your Services Layer (Business Logic Layer).
There is however, a disadvantage in using this approach, which is the fact that your unit tests (which will be using a Fake implementation of your DbContext) will be using LINQ to Objects to run your queries whereas your concrete implementation will use LINQ to Entities which does not support all LINQ to Objects methods.
There's documentation on MSDN (http://msdn.microsoft.com/en-us/library/bb738550.aspx) which highlights these differences.
I also recommend reading this article (http://kearon.blogspot.com.au/2011/02/mocking-entity-framework-4-code-first.html) which demonstrates how to make DbContext unit testable by removing the inderlying dependency on a phyiscal database.
Hope this all helps!
I have read almost all articles about Repository pattern and different implementations of it. Many of them judged bad practices (ex: using IQueryable<T> instead of IList<T>) etc. that why i'm still stuck and couldn't end-up to the right one.
So:
Do I need Repository pattern to apply IoC in my MVVM applications ?
If yes, What is the efficient IRepository implementation to EF Entities which is a good practice and better testable ?
How can I test my Repositories and UnitofWork behavior ? Unit tests against in memory Repositories ? Integration tests ?
Edit : According to answers I added the first question.
Ayende Rahien has a lot of posts about repository http://ayende.com/blog/search?q=repository and why it is bad when you are using ORM's. I thought Repository was the way to go. Maybe it was, in 2004. Not now. ORM's already implement repository. In case of EF it is IDbSet. And DbContext is UnitOfWork. Creating a repository to wrap EF or other ORM's adds a lot of unnecessary complexity.
Do integration testing of code that will interact with database.
The repository pattern adds an extra layer when you are using EF, so you should make sure that you need this extra level of indirection.
The original idea of the Repository pattern is to protect the layers above from the complexity of and knowing about the structure of the database. In many ways EF's ORM model protects the code from the physical implementation in the database so the need for a repository is less.
There are 2 basic alternatives:
Let the business layer talk directly to the EF model
Build a datalayer that implements the Repository pattern, this layers maps EF objects to POCO
For tests:
When we use EF directly we use a transaction scope with rollback, so that the tests do not change the data.
When we use the repository pattern we use Rhino Mocks to mock the repository
We use both approaches, Repository pattern gives a more clearly layered app and therefore maybe more control, using EF directly gives an app with less code and therefore faster to build.
I have a problem that I haven't been able to find a solution to, and I wonder if anyone could give some advice.
I have a mocked datacontext/objectset, done through interfaces and t4 templates, with some ninject magic, with the intent of having in memory datasets for unit testing.
However, what should you do with the foreign key values/navigation properties?
Lets say I have hotels and customers, ctx.Hotels has some values, but Customer.Hotels does not. The get is something like this if it is a one-to-one relationship:
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Hotel>("HotelModel.FK_Customers_Hotels", "Hotel").Value;
and one-to-many:
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedCollection<BookingRow>("HotelModel.FK_BookingRows_Customers", "BookingRow");
My skill level just isn't enough to even understand what is going on here.
[edit:]
Great Master Julie Lerman confirms that this is a dead end. You can't properly mock entityobjects, you need POCOs for that.
Mocking ObjectContext when you are using EntityObject based entities is mostly impossible because for example RelationshipManager is a real class which cannot be replaced with your mock. Also your entities are heavily dependent on non mockable EF code.
Note: "Mostly" because you can mock it but you need special framework intercepting calls to real objects and forwarding them to your methods instead. That is possible only with TypeMock Isolator or MS Moles.
Btw. mocking EF code is something you don't want to do - go through this answer and linked answers. Some of them targets newer EF API but the problems are still same.
I'm using Entity Framework (code first), Repositories, and the Unit of Work pattern, essentially as described here:
Entity Framework 4 CTP 4 / CTP 5 Generic Repository Pattern and Unit Testable
I'm also using StructureMap to manage my object instances and I have some code like this wiring up the EF dbcontext and unit of work:
For<DbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
I also have a generic Repository<T> that currently knows about the MyDbContext instance. Now I need to be able to support multiple databases, and thus multiple DbContexts. I'm considering trying to adjust my IUnitOfWork to be instead an IUnitOfWork<T>, where T is the DbContext to use. But my repository will also need to know which DbContext to use, so do I then have to make it doubly generic (e.g. Repository<TEntity,TDbContext>)?
What's the best, simplest way to support multiple databases using the UnitOfWork pattern I'm using?
It depends on your application logic. Are you going to do changes in multiple databases withing single unit of work? If yes you should still use one unit of work with database factory for each database accessed within that unit of work. Commit of that unit of work should use TransactionScope to make changes in all database atomically (this can be little bit more challenging).
If you always need to make changes only in a single database you can use single generic unit of work but you also have to implement generic Get on database factory. Passing context type to the repository is not needed. Move the initialization logic to concrete repositories which know the type of context they must use and they will ask database factory for that context.