我正在使用EF6中的新测试双打here from MSDN。 VS2013与Moq& NUnit的。 一切都很好,直到我不得不做这样的事情:
var myFoo = context.Foos.Find(id);
然后:
myFoo.Name = "Bar";
然后:
context.Entry(myFoo).Property("Name").IsModified = true;
此时我收到错误:
其他信息:会员' IsModified'无法召唤 财产'姓名'因为类型的实体 '富'在上下文中不存在。添加一个 实体向上下文调用Add或Attach方法 DbSet。
虽然,当我检查' Foos'在使用AddWatch的上下文中,我可以在运行测试之前看到我添加的所有项目。所以他们在那里。
我已经从文章中创建了FakeDbSet(或TestDbSet)。我将每个FakeDbSet放在构造函数中的FakeContext中,每个构造函数都被初始化。像这样:
Foos = new FakeDbSet<Foo>();
我的问题是,是否可以使用测试双打场景使用FakeDbSet和FakeContext,以便从测试双重访问DbEntityEntry和DBPropertyEntry?谢谢!
答案 0 :(得分:5)
在运行测试之前,我可以看到我添加的所有项目。他们就在那里。
实际上,您只是向ObservableCollection
添加了项目。 context.Entry
方法比这更深入。它需要更改跟踪器积极参与添加,修改和删除实体。如果你想嘲笑这个改变跟踪器,ObjectStateManager
(忽略它根本不被设计为嘲笑的事实),祝你好运!它有超过4000行代码。
DbSet
构建了一个全新的宇宙,它本身就是一个bug的来源。我决定只在我的代码中涉及EF的时间和地点进行集成测试。一个有效的端到端测试让我感觉事情还可以。单元测试(伪造EF)不是。 (别人这样做,不要误解我的意思)。
但是,让我们假设你仍然想冒险嘲笑DbContext.Entry<T>
。太糟糕了,不可能。
DbEntityEntry<T>
,一个带有内部构造函数的类,它是InternalEntityEntry
的包装器,它是一个内部类。顺便说一句,DbEntityEntry
没有实现接口。所以,回答你的问题
是否可以(...)从测试双重访问DbEntityEntry和DBPropertyEntry?
不,EF的嘲笑钩子只是非常肤浅的,你甚至都不会接近EF真正的作用。
答案 1 :(得分:0)
抽象它。如果您正在使用某个界面,那么在创建自己的双打时,请将修改过的内容放在一个单独的方法中。我的界面和实现(由EF生成,但我更改了模板)如下所示:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Model
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public interface IOmt
{
DbSet<DatabaseOmtObjectWhatever> DatabaseOmtObjectWhatever { get; set; }
int SaveChanges();
void SetModified(object entity);
void SetAdded(object entity);
}
public partial class Omt : DbContext, IOmt
{
public Omt()
: base("name=Omt")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<DatabaseOmtObjectWhatever> DatabaseOmtObjectWhatever { get; set; }
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
public void SetAdded(object entity)
{
Entry(entity).State = EntityState.Added;
}
}
}