报价在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