gpt4 book ai didi

c# - 如何在单元测试中验证EF Core DBContext配置

转载 作者:行者123 更新时间:2023-12-01 23:21:59 24 4
gpt4 key购买 nike

当前,当DBContext模型的配置中有错误时,我们会在运行时收到错误。例如:


实体类型“ MyObject”要求定义主键。如果您打算使用无钥匙实体类型,请调用“ HasNoKey()”。


在应用程序中首次使用EF Core时,会引发此错误。我想在单元测试中验证模型。

我尝试过的

我在堆栈跟踪中注意到了ModelValidator.Validate,所以我尝试了以下操作:

[TestMethod]
public void MyDbContext_DoesNotThrowExceptions()
{
// Arrange
var myDbContext = CreateMyDbContext();
IModel model = myDbContext.Model;

var validator = new ModelValidator(new ModelValidatorDependencies(???,???)) // [EntityFrameworkInternal] public ModelValidatorDependencies([NotNull] ITypeMappingSource typeMappingSource,[NotNull] IMemberClassifier memberClassifier)

// Act
validator.Validate(model, ???); // public virtual void Validate(IModel model,IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
}


不幸的是,我现在不知道如何创建 ModelValidator / ModelValidatorDependencies或作为 IDiagnosticsLogger传递的内容-请参见代码中的 ???
同样, [EntityFrameworkInternal]也使我觉得我使用了错误的方法。

有人知道如何解决此单元测试吗? (通过创建 ModelValidator或通过其他方法)

细节

错误的完整堆栈跟踪:

Test method Foo threw exception: 
System.InvalidOperationException: The entity type 'MyEntity' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'.
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNonNullPrimaryKeys(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext`1 context)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IConventionModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalized(IConventionModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_Dependencies()
at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.Microsoft.EntityFrameworkCore.Internal.IDatabaseFacadeDependenciesAccessor.get_Dependencies()
at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetFacadeDependencies(DatabaseFacade databaseFacade)
at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRaw(DatabaseFacade databaseFacade, String sql, IEnumerable`1 parameters)
at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRaw(DatabaseFacade databaseFacade, String sql, Object[] parameters)
at myCode




通过soms调整(EF Core 3验证方法具有2个参数),Vasil的答案对我有用。我现在有了:

[TestMethod]
public void MyDbContext_DoesNotThrowExceptions()
{
// Arrange
var serviceProvider = CreateServiceProvider();

var validator = serviceProvider.GetService<IModelValidator>();
var context = serviceProvider.GetService<MyDbContext>();
var logger = serviceProvider.GetService<IDiagnosticsLogger<DbLoggerCategory.Model.Validation>>();

// Act
validator.Validate(context.Model, logger);
}

private static ServiceProvider CreateServiceProvider()
{
var serviceCollection = new ServiceCollection()
.AddEntityFrameworkSqlServer()
.AddDbContext<MyDbContext>((sp, options) => options
.UseSqlServer(new SqlConnection()));
return serviceCollection.BuildServiceProvider();
}

最佳答案

我已经在EFCore github存储库中四处查看,这是我设法工作的最好成绩。

var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
serviceCollection.AddEntityFrameworkSqlServer().AddDbContext<Context>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var validator = serviceProvider.GetService<IModelValidator>();
var context = serviceProvider.GetService<Context>();

validator.Validate(context.Model);


使用的所有类型都来自ef名称空间或ef所依赖的程序包,因此您应该能够使其毫无问题地运行。

我已经用没有主键的单个实体对其进行了测试,并抛出异常“实体类型'XXXXX'需要定义主键”,因此这应该与ef在执行第一个查询时所执行的工作非常接近。

关于c# - 如何在单元测试中验证EF Core DBContext配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59732333/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com