我正在嘗試使用內存模擬上下文來測試我的存儲庫。如何模擬實體框架的導航屬性智能?
我像大多數人一樣使用內存中的字典來實現它。這會將我的存儲庫接口上的成員實現爲Add,Remove,Find等,並使用內存中的集合。
這工作正常,在大多數情況下:
[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); // passes
}
不過,我有以下的測試,我無法得到與模擬庫通過(對SQL資料庫工作正常)。
考慮我有三個倉庫:
- 帖子(處理用戶內容的帖子,像StackOverflow的問題)。
- 地點(位置在世界上,如「洛杉磯」)。
- LocationPosts(接點表處理郵件/位置之間的許多許多)。
可以將帖子添加到任何地方,也可以將它們添加到特定的位置。
現在,這裏是我的測試:
[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.
}
基本上,使用「真正的」 EF/SQL庫的時候,當我一個發佈添加到特定位置,的EntityFramework是足夠聰明地添加了「LocationPost」記錄,因爲EDMX(「郵政」實體上的「LocationPosts」導航屬性)中的關聯
但是,如何使我的Mock存儲庫足夠智能以「模仿」此EF智能?
當我做「添加」我的模擬庫,這只是添加到詞典。它沒有智慧去「哦,等等,你有一個依賴關聯,讓我把它添加到你的其他倉庫」。
我的模擬庫是通用的,所以我不知道如何把智慧放在那裏。
我也看過創建一個FakeObjectContext/FakeObjectSet(如她的博客中的Julie Lerman所建議的),但這仍然不包括這種情況。
我有一種感覺,我的嘲笑解決方案不夠好。任何人都可以提供幫助,或者提供關於如何正確地模擬覆蓋我的場景的Entity Framework 4/SQL Server存儲庫的最新文章?
問題的核心是我有每聚合根一個存儲庫(這是好的,但也是我下臺)。
所以郵政和位置都是聚集根,但既不是 「擁有」 LocationPosts。
因此,他們是3個獨立的存儲庫,而在內存中的情況下,他們是3個單獨的字典。我想我在內存回購中錯過了它們之間的「膠水」。
編輯
問題的部分原因是,我使用純POCO的(無EF代碼生成)。我也沒有任何更改跟蹤(沒有基於快照的跟蹤,沒有代理類)。
我覺得這是「智慧」發生的地方。
目前,我正在探索委託選項。我在「添加」之後在我的通用模擬存儲庫(void,接受泛型T,作爲實體)中公開了一個事件。然後,我在我的「Post Repository」中訂閱此事件,我計劃將相關實體添加到其他存儲庫。
這應該工作。如果是這樣的話,會作爲答案。
但是,我不確定這是最好的解決方案,但是再次,這只是爲了滿足嘲弄(代碼不會用於真正的功能)。
但是'OnAdd'可以是虛擬的,不是嗎? – 2012-03-19 14:48:46