![](/img/trans.png)
[英]How to scaffold DbContext with plural DbSet property names in Entity Framework Core?
[英]Dynamically Test All Entity Framework Core DbContext DbSet<> objects with xUnit
我正在使用 xUnit 和 FluentAssertions 編寫集成測試來驗證我們的模型是否正確映射。 我們有幾十個 EF 上下文,對於每個上下文,都有一個或多個DbSet<>
屬性,如下所示:
public class SomeContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder builder) { // ... }
public virtual DbSet<User> Users { get; set; }
}
它們都以相同的方式布置,因此這將是使用[MemberData]
動態獲取每個上下文作為測試和DbSet<>
屬性的輸入,調用它,並確保它不會失敗的理想選擇一個簡單的查詢。 Container.GetInstance()
調用是對我的 DI 容器的調用,以獲取實際的DbContext
對象:
public class ContextTests
{
public static IEnumerable<object[]> EntitiesMappedInCode =>
typeof(DbContextInitializer).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(DbContext)) && !t.IsAbstract)
.SelectMany(dbContextType =>
{
var context = (DbContext) Container.GetInstance(dbContextType);
var entities = context.Model.GetEntityTypes();
var dbSetProperties = context.GetType().GetProperties().Where(p =>
typeof(DbSet<>).IsAssignableFrom(p.PropertyType.GetGenericTypeDefinition()));
return dbSetProperties.Select(dbSet => new [] {context, dbSet.GetValue(context)});
});
[Theory]
[MemberData(nameof(EntitiesMappedInCode))]
public void EntitiesDefinedInCode_ExistsInDatabase(DbContext context, object dbSetObject)
{
var dbSet = dbSetObject as DbSet<dynamic>;
dbSet.Invoking(dbSet => Queryable.FirstOrDefault<dynamic>(dbSet))
.Should().NotThrow<SqlException>("the entity framework model should match the database");
}
}
問題是反射無法正常工作以返回運行時實例,並且在p.PropertyType.GetGenericTypeDefinition()
處失敗並出現錯誤。
有沒有人動態檢索上下文的DbSet<>
屬性並成功調用它們的查詢?
拋出異常是因為GetGenericTypeDefinition()
不適用於非泛型類型,因此您應該在調用它之前首先檢查類型是否實際上是泛型的:
var dbSetProps = typeof(HwContext).GetProperties().Where(c =>
c.PropertyType.IsGenericType &&
typeof(DbSet<>).IsAssignableFrom(c.PropertyType.GetGenericTypeDefinition()));
也不要DbSet<dynamic>
為DbSet<dynamic>
,只需使用dynamic
:
foreach (var prop in dbSetProps)
{
dynamic dbSet = prop.GetValue(context);
// this should not throw
Queryable.FirstOrDefault(dbSet);
}
感謝 Evk,我能夠讓它像這樣工作:
public class ContextTests
{
public static IEnumerable<object[]> EntitiesMappedInCode =>
typeof(DbContextInitializer).Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(DbContext)) && !t.IsAbstract)
.SelectMany(dbContextType =>
{
var dbSetProps = dbContextType.GetProperties()
.Where(c => c.PropertyType.IsGenericType
&& typeof(DbSet<>).IsAssignableFrom(c.PropertyType.GetGenericTypeDefinition()));
var context = Container.GetInstance(dbContextType);
return dbSetProps.Select(dbSetProp => new [] {context, dbSetProp.GetValue(context)});
});
[Theory]
[MemberData(nameof(EntitiesMappedInCode))]
public void EntitiesDefinedInCode_ExistsInDatabase(DbContext context, dynamic dbSet)
{
context.Invoking(dbContext => Queryable.FirstOrDefault(dbSet))
.Should().NotThrow<SqlException>("the entity framework model should match the database");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.