模拟entity framework数据库
我正在使用Entity Framework 4+。
是否可以使用一些随机数据从架构中自动创建一些MOCK数据库? 整合,放入整体,字符串,放置一些GUID或其他……
它可以帮助我调试我的应用程序很多。
谢谢詹姆斯
转到此链接并查看本节“在自动创建的数据库中播种初始数据”
我发现了这个与EF 4一起用于模拟数据库的好工具 。 基本上它只是一个T4模板,它既可以创建“普通”EF层,也可以创建一个可用于测试的模拟对象和接口。 这里有更多文档。
但有一点需要注意。 开箱即用它对我不起作用,因为我的存储库代码调用SaveChanges()和其他未在生成的接口中实现的方法。 通过从Microsoft的ObjectContext实现中提取接口并创建自己的IObjectContext接口,我能够解决这个问题。 然后我创建了一个基类(用于模拟),它通过简单地将每个调用委托给一个注入的模拟来实现这个接口。 这样我就可以使用Moq在我的测试类中创建该部分,同时仍然保留在生成的模拟中跟踪插入,更新和删除的function。
以下是我对“Context”T4模板的更改以解决此问题。 很抱歉这样做的一点点零碎 – 所以我没有让我发布整个代码清单,因为它太长了。
在fileManager.Process();
之前添加此代码fileManager.Process();
fileManager.StartNewFile( "IObjectContext.cs"); WriteHeader(); WriteHeaderIncludeSystem(); WriteHeaderIncludeData(); WriteHeaderIncludeContainers(); WriteNamespaceBegin( code, namespaceName ); WriteObjectContextInterface( container, code ); WriteNamespaceEnd( namespaceName ); fileManager.StartNewFile( container.Name + "Mock.ObjectContext.cs"); WriteHeader(); WriteHeaderIncludeSystem(); WriteHeaderIncludeData(); WriteHeaderIncludeContainers(); WriteNamespaceBegin( code, namespaceName ); WriteObjectContextMockBase( container, code ); WriteNamespaceEnd( namespaceName );
在WriteInterface()
块之后添加此代码。
<#+ void WriteObjectContextInterface( EntityContainer container, CodeGenerationTools code ) { #> /// /// The interface for the generic object context. This contains all of /// the ObjectContext
properties that are implemented in the /// concrete ObjectContext class. This interface was created so these members /// can be mocked, as ObjectContext doesn't have a default public constructor. /// <#=Accessibility.ForType(container)#> interface IObjectContext : IDisposable { void AcceptAllChanges(); void AddObject(string entitySetName, object entity); TEntity ApplyCurrentValues(string entitySetName, TEntity currentEntity) where TEntity : class; TEntity ApplyOriginalValues (string entitySetName, TEntity originalEntity) where TEntity : class; void ApplyPropertyChanges(string entitySetName, object changed); void Attach(System.Data.Objects.DataClasses.IEntityWithKey entity); void AttachTo(string entitySetName, object entity); int? CommandTimeout { get; set; } DbConnection Connection { get; } ObjectContextOptions ContextOptions { get; } void CreateDatabase(); string CreateDatabaseScript(); EntityKey CreateEntityKey(string entitySetName, object entity); T CreateObject() where T : class; ObjectSet CreateObjectSet () where TEntity : class; ObjectSet CreateObjectSet (string entitySetName) where TEntity : class; void CreateProxyTypes(IEnumerable types); ObjectQuery CreateQuery (string queryString, params ObjectParameter[] parameters); bool DatabaseExists(); string DefaultContainerName { get; set; } void DeleteDatabase(); void DeleteObject(object entity); void Detach(object entity); void DetectChanges(); void Dispose(); int ExecuteFunction(string functionName, params ObjectParameter[] parameters); ObjectResult ExecuteFunction (string functionName, params ObjectParameter[] parameters); ObjectResult ExecuteFunction (string functionName, MergeOption mergeOption, params ObjectParameter[] parameters); int ExecuteStoreCommand(string commandText, params object[] parameters); ObjectResult ExecuteStoreQuery (string commandText, params object[] parameters); ObjectResult ExecuteStoreQuery (string commandText, string entitySetName, MergeOption mergeOption, params object[] parameters); object GetObjectByKey(System.Data.EntityKey key); void LoadProperty(object entity, string navigationProperty); void LoadProperty(object entity, string navigationProperty, MergeOption mergeOption); void LoadProperty (TEntity entity, Expression> selector); void LoadProperty (TEntity entity, Expression> selector, MergeOption mergeOption); System.Data.Metadata.Edm.MetadataWorkspace MetadataWorkspace { get; } ObjectStateManager ObjectStateManager { get; } void Refresh(RefreshMode refreshMode, IEnumerable collection); void Refresh(RefreshMode refreshMode, object entity); int SaveChanges(); int SaveChanges(bool acceptChangesDuringSave); int SaveChanges(SaveOptions options); ObjectResult Translate (DbDataReader reader); ObjectResult Translate (DbDataReader reader, string entitySetName, MergeOption mergeOption); bool TryGetObjectByKey(EntityKey key, out object value); } <#+ } #> <#+ void WriteObjectContextMockBase( EntityContainer container, CodeGenerationTools code ) { #> /// /// The default concrete implementation of IObjectContext that will be used for mocking. /// This contains all of the IObjectContext
members that are implemented in the /// concrete ObjectContext class. This class was created so these members /// can be mocked. /// <#=Accessibility.ForType(container)#> abstract class ObjectContextMockBase : IObjectContext { private readonly IObjectContext _objectContext; public ObjectContextMockBase(IObjectContext objectContext) { if (objectContext == null) throw new System.ArgumentNullException("objectContext"); _objectContext = objectContext; } public virtual void AcceptAllChanges() { _objectContext.AcceptAllChanges(); } public virtual void AddObject(string entitySetName, object entity) { _objectContext.AddObject(entitySetName, entity); } public virtual TEntity ApplyCurrentValues (string entitySetName, TEntity currentEntity) where TEntity : class { return _objectContext.ApplyCurrentValues (entitySetName, currentEntity); } public virtual TEntity ApplyOriginalValues (string entitySetName, TEntity originalEntity) where TEntity : class { return ApplyOriginalValues (entitySetName, originalEntity); } public virtual void ApplyPropertyChanges(string entitySetName, object changed) { _objectContext.ApplyPropertyChanges(entitySetName, changed); } public virtual void Attach(System.Data.Objects.DataClasses.IEntityWithKey entity) { _objectContext.Attach(entity); } public virtual void AttachTo(string entitySetName, object entity) { _objectContext.AttachTo(entitySetName, entity); } public virtual int? CommandTimeout { get { return _objectContext.CommandTimeout; } set { _objectContext.CommandTimeout = value; } } public virtual DbConnection Connection { get { return _objectContext.Connection; } } public virtual ObjectContextOptions ContextOptions { get { return _objectContext.ContextOptions; } } public virtual void CreateDatabase() { _objectContext.CreateDatabase(); } public virtual string CreateDatabaseScript() { return _objectContext.CreateDatabaseScript(); } public virtual EntityKey CreateEntityKey(string entitySetName, object entity) { return _objectContext.CreateEntityKey(entitySetName, entity); } public virtual T CreateObject() where T : class { return _objectContext.CreateObject (); } public virtual ObjectSet CreateObjectSet () where TEntity : class { return _objectContext.CreateObjectSet (); } public virtual ObjectSet CreateObjectSet (string entitySetName) where TEntity : class { return _objectContext.CreateObjectSet (entitySetName); } public virtual void CreateProxyTypes(IEnumerable types) { _objectContext.CreateProxyTypes(types); } public virtual ObjectQuery CreateQuery (string queryString, params ObjectParameter[] parameters) { return _objectContext.CreateQuery (queryString, parameters); } public virtual bool DatabaseExists() { return _objectContext.DatabaseExists(); } public virtual string DefaultContainerName { get { return _objectContext.DefaultContainerName; } set { _objectContext.DefaultContainerName = value; } } public virtual void DeleteDatabase() { _objectContext.DeleteDatabase(); } public virtual void DeleteObject(object entity) { _objectContext.DeleteObject(entity); } public virtual void Detach(object entity) { _objectContext.Detach(entity); } public virtual void DetectChanges() { _objectContext.DetectChanges(); } public virtual void Dispose() { _objectContext.Dispose(); } public virtual int ExecuteFunction(string functionName, params ObjectParameter[] parameters) { return _objectContext.ExecuteFunction(functionName, parameters); } public virtual ObjectResult ExecuteFunction (string functionName, params ObjectParameter[] parameters) { return _objectContext.ExecuteFunction (functionName, parameters); } public virtual ObjectResult ExecuteFunction (string functionName, MergeOption mergeOption, params ObjectParameter[] parameters) { return _objectContext.ExecuteFunction (functionName, mergeOption, parameters); } public virtual int ExecuteStoreCommand(string commandText, params object[] parameters) { return _objectContext.ExecuteStoreCommand(commandText, parameters); } public virtual ObjectResult ExecuteStoreQuery (string commandText, params object[] parameters) { return _objectContext.ExecuteStoreQuery (commandText, parameters); } public virtual ObjectResult ExecuteStoreQuery (string commandText, string entitySetName, MergeOption mergeOption, params object[] parameters) { return _objectContext.ExecuteStoreQuery (commandText, entitySetName, mergeOption, parameters); } public virtual object GetObjectByKey(EntityKey key) { return _objectContext.GetObjectByKey(key); } public virtual void LoadProperty(object entity, string navigationProperty) { _objectContext.LoadProperty(entity, navigationProperty); } public virtual void LoadProperty(object entity, string navigationProperty, MergeOption mergeOption) { _objectContext.LoadProperty(entity, navigationProperty, mergeOption); } public virtual void LoadProperty (TEntity entity, Expression> selector) { _objectContext.LoadProperty (entity, selector); } public virtual void LoadProperty (TEntity entity, Expression> selector, MergeOption mergeOption) { _objectContext.LoadProperty (entity, selector, mergeOption); } public virtual System.Data.Metadata.Edm.MetadataWorkspace MetadataWorkspace { get { return _objectContext.MetadataWorkspace; } } public virtual ObjectStateManager ObjectStateManager { get { return _objectContext.ObjectStateManager; } } public virtual void Refresh(RefreshMode refreshMode, IEnumerable collection) { _objectContext.Refresh(refreshMode, collection); } public virtual void Refresh(RefreshMode refreshMode, object entity) { _objectContext.Refresh(refreshMode, entity); } public virtual int SaveChanges() { return _objectContext.SaveChanges(); } public virtual int SaveChanges(bool acceptChangesDuringSave) { return _objectContext.SaveChanges(acceptChangesDuringSave); } public virtual int SaveChanges(SaveOptions options) { return _objectContext.SaveChanges(options); } public virtual ObjectResult Translate (DbDataReader reader) { return _objectContext.Translate (reader); } public virtual ObjectResult Translate (DbDataReader reader, string entitySetName, MergeOption mergeOption) { return _objectContext.Translate (reader, entitySetName, mergeOption); } public virtual bool TryGetObjectByKey(EntityKey key, out object value) { return _objectContext.TryGetObjectByKey(key, out value); } } <#+ } #>
WriteMockContextBody()
(注释后)的前两行(第二行是大括号) WriteMockContextBody()
为
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#>Mock : ObjectContextMockBase, I<#=code.Escape(container)#> { public <#=code.Escape(container)#>Mock(IObjectContext objectContext) : base(objectContext) { }
将WriteInterface()
的第一行(在注释之后)更改为
<#=Accessibility.ForType(container)#> interface I<#=code.Escape(container)#> : IObjectContext
我还应该注意到,我还没有对此进行过多次测试,但我确实做了一些基本的validation以确保它的function。
这是有助于生成测试数据的库 – http://autopoco.codeplex.com/
请参阅Rab Hallett的博客,题为“ ADO.NET模拟上下文生成器:Visual Studio 2010模板”
Rab使用T4模板为EF创建界面。
您可以查看有关Visual Studio for Database Professionals的此主题 。 或者RedGate有一个类似的工具 。 我不知道有任何免费的工具可以做到这一点。