用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
。 由于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());
}
}
链接地址: 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?