【发布时间】:2010-07-13 18:28:07
【问题描述】:
我正在尝试为ObjectContext 创建一个抽象层。我了解 OC 是一个工作单元,但我只是不完全了解如何为它编写一个好的界面。理想情况下,我希望能够将实现IDataContext 的“RealDataContext”换成完全在内存中的“FakeDataContext”之类的东西。
这样做的原因是我希望能够针对内存数据库测试我的存储库。
谢谢!
【问题讨论】:
标签: c# entity-framework
我正在尝试为ObjectContext 创建一个抽象层。我了解 OC 是一个工作单元,但我只是不完全了解如何为它编写一个好的界面。理想情况下,我希望能够将实现IDataContext 的“RealDataContext”换成完全在内存中的“FakeDataContext”之类的东西。
这样做的原因是我希望能够针对内存数据库测试我的存储库。
谢谢!
【问题讨论】:
标签: c# entity-framework
您应该能够创建派生自 ObjectContext 并实现 IDataContext 接口的扩展类。为了真正能够模拟 ObjectContext,您的 IDataContext 接口需要为您正在使用并希望模拟的任何 ObjectContext 成员包含匹配的签名(或属性)。类似以下内容就足够了:
interface IDataContext, IDisposable
{
void AddObject(string entitySetName, object entity);
void Attach(IEntityWithKey entity);
void Detach(object entity);
void DeleteObject(object entity);
int SaveChanges();
int SaveChanges(bool acceptChangesDuringSave);
int SaveChanges(SaveOptions options);
// Any other members you wish to be mockable
}
class DataContext: ObjectContext, IDataContext
{
// nothing here
}
从技术上讲,由于 DataContext 继承了 ObjectContect 的所有内容,因此 IDataContext 的实现由 ObjectContext 负责。您不需要在 DataContext 类中进行任何额外的实现。只要您始终注入(或使用工厂创建)IDataContext 实例而不是 ObjectContext,您应该能够在测试时模拟 IDataContext:
class SomeEntityRepository: IRepository<SomeEntity>
{
public SomeEntityRepository(IDataContext context)
{
m_context = context;
}
private readonly IDataContext m_context;
public SomeEntity GetById(long id)
{
// implementation
}
}
// xUnit.NET & Moq
class SomeEntityRepositoryTests
{
[Fact]
public void GetById_returns_entity_when_valid_id_is_passed()
{
// state and context
var mockContext = new Mock<IDataContext>();
// arrangement
mockContext.Setup(/* configure mock context here */);
var repo = new SomeEntityRepository(mockContext.Object);
// activity
var entity = repo.GetById(100);
// assertions
}
}
【讨论】: