I've been trying to find a good solution to this but with no luck, so either I'm not searching for the right keywords, or we're doing things wrong from the start so the problem shouldn't really exist.
Update for clarification: I would like this to work as a unit test rather than as an integration test, so I don't want this to hit the database, but I want to mock the associations made when EF persists changes in my unit test.
Original question:
Say you are testing a service method like so:
[Test]
public void AssignAuthorToBook_NewBookNewAuthor_SuccessfullyAssigned()
{
IBookService service = new BookService();
var book = new Book();
var Author = new Author() { Id = 123 };
service.AssignAuthorToBook(book, author);
Assert.AreEqual(book.AuthorId, 123);
}
Now lets say that this test fails because AssignAuthorToBook
actually works using the code book.Author = author;
so it is not assigning the AuthorId
, it is assigning the entity. When this is persisted using the Entity Framework SaveChanges()
method on the context it will associate the entities and the IDs will correlate. However, in my example above the logic of Entity Framework would not have been applied. What I am saying is the code will work once SaveChanges()
has been called, but the unit test will fail.
In this simple example, you'd probably know straight away why your test had failed as you had just written the test immediately before the code and could easily fix it. However, for more complicated operations and for operations where future changes that may change the way entities are associated, which will break tests but may not break functionality, how is unit testing best approached?
My thoughts are:
- The service layer should be ignorant of the persistence layer - should we mock the Data Context in the unit tests to mock the manner that it works? Is there an easy way to do this that will automatically tie up the associations (i.e. assign to correct entity if
Id
is used or assign the correctId
if the entity is used)? - Or should the tests be structured in a slightly different manner?
The tests that exist in the current project I have inherited work as in my example above, but it niggles with me that there is something wrong with the approach and that I haven't managed to find a simple solution to a possibly common problem. I believe the Data Context should be mocked, but this seems like a lot of code will need to be added to the mock to dynamically create the associations - surely this has already been solved?
Update: These are the closest answers I've found so far, but they're not quite what I'm after. I don't want to test EF as such, I just wondered what was best practise for testing service methods that access repositories (either directly or via navigation properties through other repositories sharing the same context).
How Do I Mock Entity Framework's Navigational Property Intelligence?
Mocked datacontext and foreign keys/navigation properties
Fake DbContext of Entity Framework 4.1 to Test
Navigation properties not set when using ADO.NET Mocking Context Generator
Conclusion so far: That this is not possible using unit testing, and only possible using integration testing with a real DB. You can get close and probably code something to dynamically associate the navigation properties, but your mock data context will never quite replicate the real context. I would be happy if any solution enabled me to automatically associate the navigation properties which would allow my unit tests to be better, if not perfect (the nature of a successful unit test doesn't by any means guarantee functionality anyway) The ADO.NET Mocking Context Generator comes close, but it appears that I'll have to have a mock version of every entity which will not work for me in case functioanlity is added to them using partial classes in my implementation.