Answered by:
Unit Testing EF6 with Include

Question
-
This article on msdn describes using moq to unit test service classes that depend on EF6 DbContext.
The approach shown in the article works fine. The problem is that when you add an "include" to your query, you received an ArgumentNullException.
i.e.: this (from the article) works fine
public List<Blog> GetAllBlogs() { var query = from b in _context.Blogs orderby b.Name select b; return query.ToList(); }
but this doesn't
public List<Blog> GetAllBlogs() { var query = from b in _context.Blogs.Include("Posts") orderby b.Name select b; return query.ToList(); }Can anyone offer a fix?
Thanks
Saturday, September 28, 2013 11:57 PM
Answers
-
I have worked on a few projects using an ORM like nHibernate, EF and in-house written object code generators and not one time have I seen the ORM or the generator code being unit tested.
However, you could UT the DAL if the DAL object is using an Interface with mocking out the DAL methods and mocking up data the DAL methods would use, instead of actually making the call to the ORM that the DAL methods would do. I consider that UT-ing.
The thing about UT EF itself? What can I say about it, other than I wouldn't be doing it, and I would be doing functional testing with a test harness against the ORM as needed exercising the methods in the DAL objects that are making actual calls to the ORM to persist or retrieve data with the ORM. Of course, the functional tests are not part of the build process, because the data is subject to change that could make tests fail stopping the build.
That's the test I would be doing, and I don't see the point of a UT for the ORM. I don't see it nor would I use it.
Monday, September 30, 2013 8:51 PM
All replies
-
<copied>
The approach shown in the article works fine. The problem is that when you add an "include" to your query, you received an ArgumentNullException
<end>
How can you do an "include" when you never mocked up some in memory data for the "Posts". I don't know if you can even mock up "Post" data and include it in the query in this situation. It doesn't look like you can, since you got a Null exception.
I am not trying to be smart with you. But I wouldn't waste my time trying to do some kind of a unit test with EF. I do Functional tests against EF, go after real data in the database and test for expected results returned. If the test didn't blow up, and it passed the Asserts that are being applied against return result, then I am done with it, which I do when I on a contract.
- Proposed as answer by Fred Bao Monday, September 30, 2013 4:30 AM
- Unproposed as answer by SeligDrahcir Monday, September 30, 2013 8:36 AM
Sunday, September 29, 2013 2:45 AM -
Julie Lerman has a good guide to mocking with EF (hand baked rather than with Moq) which covers handling the Include method here (you create your own extension method to handle the Include call). The good news is once you've worked it out once it all ends up being reasonably re-usable. You do definitely want to be mocking your repository for unit testing (otherwise it isn't unit testing).
- Proposed as answer by Fred Bao Monday, September 30, 2013 4:30 AM
- Unproposed as answer by SeligDrahcir Monday, September 30, 2013 8:37 AM
Sunday, September 29, 2013 3:22 AM -
I tried mocking Posts too. My mocked context returned mocked sets for Blogs and for Posts. Each worked independently but any query that attempted to join the two failed with null exceptions.
I agree with your comments regarding unit testing EF. In EF5 I do pretty much as you describe. But I think this is a compromise. It says something like "I can't unit test my EF code so I'll jump straight to integration tests".
The article caught my attention because it suggests that the EF team have given some thought to this problem and improved things in EF6. But it appears this will only be the case if queries exclude the use of "include". In my opinion this isn't much of an improvement because I think the majority of queries do use "include". But I'm pretty sure the EF team know that and hence I'm pretty sure they would have allowed for it in their solution. So my thought is that I've missed something.
Monday, September 30, 2013 8:35 AM -
I would say that the Unit Tests for EF would be more viable using an EF code first approach where you would make the entities by hand with relationships objects in the parent. I don't think the code first approach uses includes.
What I would unit test would be the BLL objects, mock up data for the methods, mock out the methods themselves and not be bothered with the UT of an ORM. I functional tested the DAL and the ORM that the DAL is using to make sure that this work from that standpoint, and I am doing UT at the BLL.
Monday, September 30, 2013 2:15 PM -
We're using code first for our current project. We use "include" all the time. How else would we populate the context with related entities? Maybe you mean lazy loading? But I'm almost certain you can lazy load with database, model and code first approaches, so I'm not sure this is relevant.
Discussions regarding what to test and what not to test are moot points in the light of an article that explains how to test. The fact that someone in the EF team has written the article does at least suggest they anticipate that someone's going to do so. But my question remains how to do this for queries that contain an include clause.
Monday, September 30, 2013 2:48 PM -
I have worked on a few projects using an ORM like nHibernate, EF and in-house written object code generators and not one time have I seen the ORM or the generator code being unit tested.
However, you could UT the DAL if the DAL object is using an Interface with mocking out the DAL methods and mocking up data the DAL methods would use, instead of actually making the call to the ORM that the DAL methods would do. I consider that UT-ing.
The thing about UT EF itself? What can I say about it, other than I wouldn't be doing it, and I would be doing functional testing with a test harness against the ORM as needed exercising the methods in the DAL objects that are making actual calls to the ORM to persist or retrieve data with the ORM. Of course, the functional tests are not part of the build process, because the data is subject to change that could make tests fail stopping the build.
That's the test I would be doing, and I don't see the point of a UT for the ORM. I don't see it nor would I use it.
Monday, September 30, 2013 8:51 PM -
This may help, I just went through the same mess to arrive at a very logical conclusion...
Friday, December 13, 2013 5:12 PM