報價在The Art Of Unit Testing:
沒有面向對象的問題,不能通過添加一個間接層來解決,當然除了間接層太多以外。
下面是我可嘲笑的EF4 POCO設置。我沒有使用T4,因爲它很難弄清楚如何清理模板以避免產生太多的垃圾。你當然可以破解T4模板來吐出像這樣的結構。
訣竅是手動創建ObjectSet<T>
s並將它們暴露爲IQueryable
。由於Add
和Create
位於ObjectSet<T>
/ObjectSet<T>
,我還必須添加添加和創建實體的方法。現在
public interface IStackTagzContext {
IQueryable<Question> Questions { get; }
Question CreateQuestion();
void CreateQuestion(Question question);
void SaveChanges();
}
public class StackTagzContext : ObjectContext, IStackTagzContext {
public StackTagzContext() : base("name=myEntities", "myEntities")
{
base.ContextOptions.LazyLoadingEnabled = true;
m_Questions = CreateObjectSet<Question>();
}
#region IStackTagzContext Members
private ObjectSet<Question> m_Questions;
public IQueryable<Question> Questions {
get { return m_Questions; }
}
public Question CreateQuestion() {
return m_Questions.CreateObject();
}
public void AddQuestion(Question question) {
m_Questions.AddeObject(question);
}
public new void SaveChanges() {
base.SaveChanges();
}
#endregion
}
,你會注意到在接口上的實體集合類型IQueryable<T>
,而不是IObjectSet<T>
。我不能打擾FakeObjectSet
和IQueryable
爲我提供了足夠的靈活性。所以爲了KISS,我沒有它。
嘲笑IQueryable
,在另一方面,是微不足道的:
using Moq;
[TestClass]
public class TestClass {
Mock<IStackTagzContext> m_EntitiesMock = new Mock<IStackTagzContext>();
[TestMethod()]
public void GetShouldFilterBySite() {
QuestionsRepository target = new QuestionsRepository(m_EntitiesMock.Object);
m_EntitiesMock.Setup(e=>e.Questions).Returns(new [] {
new Question{Site = "site1", QuestionId = 1, Date = new DateTime(2010, 06,23)},
}.AsQueryable());
}
}
Mayby我懷念的理解,我只是立足這篇文章。我知道作者有POCOS類,但是我有大的已經存在的數據庫,我必須從這個數據庫創建edmx,然後在很多困難之後(這是Oracle數據庫),我能夠使用T4模板生成POCO類,因爲我沒有親手寫下他們。現在我想添加單元測試,如果要測試存儲庫,我必須模擬我的上下文對象。 因此,T4爲Context創建了實體和類的POCO類,但是這個上下文缺少接口,所以我無法基於此接口創建模擬。 – Simon 2010-09-01 13:25:47
感謝 http://slappyza.wordpress.com/2010/08/08/getting-the-entity-framework-to-generate-an-interface-for-mocking/ 我現在已經解決了問題.. 。:) – Simon 2010-09-01 13:26:33
+1。真的,所有需要發生的事情就是將'I'添加到現有的ObjectSet ...聲明中... – 2010-09-01 13:29:14