这是比实际问题更多的解决方案/解决方法。我将其发布在这里是因为在堆栈溢出或经过大量谷歌搜索后找不到此解决方案。 问题:我有一个首先要使用EF 4代码的MVC 3 Web应用程序,我想为其编写单元测试。在编写代码时,我还使用NCrunch快速运行单元测试,因此我想避免在此处返回到实际数据库。 其他解决方案:IDataContext我发现这是创建内存数据上下文的最被接受的方法。它实际上涉及为MyDataContext编写接口(interface)IMyDataContext,然后在所有 Controller 中使用该接口(interface)。一个示例是here。这是我最初使用的路线,甚至我还写了一个T4模板来从MyDataContext中提取IMyDataContext,因为我不想维护重复的相关代码。但是,我很快发现使用IMyDataContext而不是MyDataContext时,某些Linq语句在生产中失败。具体来说,像这样的查询会引发NotSupportedExceptionvar siteList = from iSite in MyDataContext.Sites let iMaxPageImpression = (from iPage in MyDataContext.Pages where iSite.SiteId == iPage.SiteId select iPage.AvgMonthlyImpressions).Max() select new { Site = iSite, MaxImpressions = iMaxPageImpression }; 我的解决方案这实际上很简单。我只是创建了MyDataContext的MyInMemoryDataContext子类,并覆盖了所有IDbSet 属性,如下所示:public class InMemoryDataContext : MyDataContext, IObjectContextAdapter{ /// <summary>Whether SaveChanges() was called on the DataContext</summary> public bool SaveChangesWasCalled { get; private set; } public InMemoryDataContext() { InitializeDataContextProperties(); SaveChangesWasCalled = false; } /// <summary> /// Initialize all MyDataContext properties with appropriate container types /// </summary> private void InitializeDataContextProperties() { Type myType = GetType().BaseType; // We have to do this since private Property.Set methods are not accessible through GetType() // ** Initialize all IDbSet<T> properties with CollectionDbSet<T> instances var DbSets = myType.GetProperties().Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>)).ToList(); foreach (var iDbSetProperty in DbSets) { var concreteCollectionType = typeof(CollectionDbSet<>).MakeGenericType(iDbSetProperty.PropertyType.GetGenericArguments()); var collectionInstance = Activator.CreateInstance(concreteCollectionType); iDbSetProperty.SetValue(this, collectionInstance,null); } } ObjectContext IObjectContextAdapter.ObjectContext { get { return null; } } public override int SaveChanges() { SaveChangesWasCalled = true; return -1; }}在这种情况下,我的CollectionDbSet 是FakeDbSet here的略微修改版本(它仅使用基础ObservableCollection和ObservableCollection.AsQueryable()实现IDbSet)。该解决方案非常适合我的所有单元测试,尤其是与NCrunch即时运行这些测试的情况。 全面集成测试这些单元测试可以测试所有业务逻辑,但是一个主要的缺点是,不能保证您的LINQ语句都不能与实际的MyDataContext一起使用。这是因为针对内存中数据上下文进行测试意味着您要替换Linq-To-Entity提供程序,而要替换Linq-To-Objects提供程序(在this SO问题的答案中很好地指出)。为了解决这个问题,我在单元测试中使用了Ninject并设置了InMemoryDataContext进行绑定(bind),而不是在单元测试中设置了MyDataContext。然后,您可以在运行集成测试时使用Ninject绑定(bind)到实际的MyDataContext(通过app.config中的设置)。if(Global.RunIntegrationTest) DependencyInjector.Bind<MyDataContext>().To<MyDataContext>().InSingletonScope();else DependencyInjector.Bind<MyDataContext>().To<InMemoryDataContext>().InSingletonScope();让我知道您是否对此有任何反馈,但是总会有待改进。 (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 根据我在问题中的评论,这更多地是为了帮助其他人在SO上搜索此问题。但是正如该问题下面的评论所指出的那样,还有很多其他设计方法可以解决此问题。 (adsbygoogle = window.adsbygoogle || []).push({}); 10-05 18:06