用POCO和t4模板测试EF 4.0

我试图创建假的上下文相关http://blogs.msdn.com/b/adonet/archive/2009/12/17/walkthrough-test-driven-development-with-the-entity-framework-4- 0.aspx

正如我所看到的,有一个接口公开了返回IObjectSet <...>的方法,但T4模板生成的方法返回ObjectSet <...>并且没有生成接口,并且在该页面上,作者将接口添加到创建的上下文中它给他的方式来创建模拟等。

我的主要目标是使用T4模板来生成poco类并创建模拟/伪造上下文来测试我的定制存储库。 有没有什么办法可以让它在没有写入或改变T4模板的情况下工作? 如何在上下文中创建模拟(对于IObjectSet不是微不足道的),如果它返回的是ObjectSet而不是IObjectSets ...

Thx提前


作者只是嘲笑仓库,而不是实体。 EntityFramework生成ObjectQueries,但他包装它们,他的存储库返回IObjectQueries。 他这样做,以便他可以轻松地嘲笑数据,然后在保存期间他只验证实体。

如果您只是想创建一个“模拟”存储库,则可以创建自己的T4模板并遍历edmx文件并生成代码。 但是没有必要产生POCOS的理由? 它们已经存在,为什么你需要重新创建它们? 他将所有东西都抽象成一个“通用”的FakeObjectSet,所以实际上没有太多的代码要写入?

你是否想要生成这个:

   public IObjectSet<Blog> Blogs
    {
        get
        {
            return _blogs ?? (_blogs = new FakeObjectSet<Blog>());
        }
        set
        {
            _blogs = value as FakeObjectSet<Blog>;
        }
    }
    private FakeObjectSet<Blog> _blogs;

如果是这样,我会猜测你会花更多的时间用T4,那么你只会写它。


没有类声明的例子T4 ...你可以通过关注这个博客来完成整个t4

<#
    foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
    {
#>
public IObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>
{
    get{
       return <#=code.FieldName(set)#> ??  ( <#=code.FieldName(set)#> = FakeObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>("<#=set.Name#>"));
    }
    set{
   <#=code.FieldName(set)#>  = value as FakeObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>>("<#=set.Name#>");
    }
}
 private FakeObjectSet<<#=MultiSchemaEscape(set.ElementType, code)#>> <#=code.FieldName(set)#>;
<#
 }

#>

这将生成此代码:

public IObjectSet<Blogs>{
  get{
     return _Blogs??  ( _Blogs = FakeObjectSet<Blog>("Blogs"));
   }
  set{
    _Blogs= value as FakeObjectSet<Class>("Blogs");
  }
}

private FakeObjectSet<Blog> _Blogs;

边注。

IObjectSet包含在System.Data中,因此请添加对System.Data.Entity.dll的引用


在单元测试的艺术中引用Roy Osherove:

没有任何面向对象的问题不能通过添加一个间接层来解决,当然除了间接层太多以外。

以下是我可嘲弄的EF4 POCO设置。 我没有使用T4,因为它很难弄清楚如何清理模板以避免产生太多的垃圾。 你当然可以破解T4模板来吐出像这样的结构。

诀窍是手动创建ObjectSet<T> s并将它们公开为IQueryable 。 由于AddCreate位于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());
  }
}
链接地址: http://www.djcxy.com/p/47573.html

上一篇: Testing EF 4.0 with POCO and t4 templates

下一篇: Is it possible to work out where in a p's text a mouse click event occurred?