I am trying to test my repository using a flash context in memory.
I implement this with a dictionary in mind, as most people do. This implements members in my repository interface for adding, deleting, searching, etc., working with the collection in memory.
This works fine in most scenarios:
[TestMethod] public void CanAddPost() { IRepository<Post> repo = new MockRepository<Post>(); repo.Add(new Post { Title = "foo" }); var postJustAdded = repo.Find(t => t.Title == "foo").SingleOrDefault(); Assert.IsNotNull(postJustAdded);
However, I have the following test, which I cannot pass using the mock repository (works fine for SQL repository).
I have three repositories:
- Messages (processes messages of user content, for example, a StackOverflow question).
- Location (locations in the world such as Los Angeles).
- LocationPosts (connection table for processing many, many messages / locations).
Messages can be added to nowhere, or they can also be added at a specific location.
Now here is my test:
[TestMethod] public void CanAddPostToLocation() { var location = locationRepository.FindSingle(1); // Get LA var post = new Post { Title = "foo", Location = location }; // Create post, with LA as Location. postRepository.Add(post); // Add Post to repository var allPostsForLocation = locationPostRepository.FindAll(1); // Get all LA posts. Assert.IsTrue(allPostsForLocation.Contains(post)); // works for EF, fails for Mock. }
Basically, when using the "real" EF / SQL repository, when I add a message to a specific place, EntityFramework is smart enough to add a "LocationPost" entry due to association in the EDMX ("LocationPosts" property on the Publish object))
But how can I make my Mock repository smart enough to "simulate" this EF intelligence?
When I do "Add" in my wet repository, it just adds to the dictionary. He has no skills to go. "Oh wait, you have a dependent association, let me add this to the OTHER repository for you."
My Mock repository is shared, so I don't know how to put smarts there.
I also considered creating a FakeObjectContext / FakeObjectSet (as Julia Lerman advises on my blog), but this still does not cover this scenario.
I have the feeling that my mocking decision is not enough. Can someone help or provide an updated article on how to properly mock the Entity Framework 4 / SQL Server repository spanning my script?
Nucleus problems: I have one repository per aggregated root (this is good, but also my fall).
So Post and Location are both cumulative roots, but do not “own” LocationPosts .
Therefore, they represent 3 separate repositories, and according to the script in memory - 3 separate dictionaries. I think I have no “glue” between them in my repo in my memory.
EDIT
Part of the problem is that I am using Pure POCO (without generating EF code). I also don't have change tracking (no snapshot based tracking, no proxy classes).
I get the impression that "skill" is happening here.
I am currently studying a delegate option. I expose an event in my general Mock repository (void, accepts a common T, which is Entity), which I call after "Add". Then I subscribe to this event in my "Post Repository", where I plan to add related objects to other repositories.
That should work. Put the answer if he does.
However, I'm not sure if this is the best solution, but again, this is only to satisfy ridicule (the code will not be used for real functionality).