在The Art Of Unit Testing Roy Osherove 中引用:
没有什么面向对象的问题不能通过增加一层间接层来解决,当然,除了太多的间接层。
以下是我的可模拟 EF4 POCO 设置。我没有使用 T4,因为很难弄清楚如何清理模板以不产生过多的 gumpf。你当然可以破解 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 为我提供了足够的灵活性。所以为了亲吻,我没有它。
另一方面,嘲笑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());
}
}