当字段设置为必需时,EF inMemory 提供程序错误地接受空条目

egm*_*frs 3 c# asp.net-mvc unit-testing entity-framework

这是我的集成测试代码:

[Fact(DisplayName = "Should only add AssetType when Name Provided")]
public async Task Test4()
{
    using (var context = GetContext()) {

        var listAssetTypes = await context.AssetType.ToListAsync();

        Assert.Equal(0, listAssetTypes.Count);

        var goodAssetType = new AssetType { Name = "1st Item" };
        context.Add(goodAssetType);
        await context.SaveChangesAsync();
        listAssetTypes = await context.AssetType.ToListAsync();

        Assert.Equal(1, listAssetTypes.Count);

        var badAssetType = new AssetType {};
        context.Add(badAssetType);
        await context.SaveChangesAsync();
        listAssetTypes = await context.AssetType.ToListAsync();

        Assert.Equal(1, listAssetTypes.Count);
    }
}
Run Code Online (Sandbox Code Playgroud)

前两个断言通过。第三次失败,实际为 2,如果我调试,我可以看到一个新的 Id 已分配,名称设置为空。

这是我的上下文方法:

private WorldContext GetContext()
{
    var builder = new ConfigurationBuilder();
    var config = builder.Build();
    var options = new DbContextOptionsBuilder<WorldContext>()
        .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
    var context = new WorldContext(config, options);
    return context;
}
Run Code Online (Sandbox Code Playgroud)

还有我的模型:

public class AssetType
{
    [DatabaseGenerated(databaseGeneratedOption: DatabaseGeneratedOption.Identity)]
    [Key]
    public int AssetTypeId { get; set; }
    [Required]
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Tse*_*eng 6

请注意,InMemory 提供程序不是生产就绪的关系数据库提供程序,仅用于协助集成测试。

它不会(必然)强制您的数据的一致性或确保约束得到满足,就像真正的数据库提供者会做的那样。

这是明确记录和预期的行为,请阅读文档“使用 InMemory 测试

InMemory 不是关系数据库

EF Core 数据库提供程序不必是关系数据库。InMemory 被设计为用于测试的通用数据库,而不是为了模仿关系数据库而设计的。

这方面的一些例子包括:

  • InMemory 将允许您保存在关系数据库中违反参照完整性约束的数据。
  • 如果您将 DefaultValueSql(string) 用于模型中的属性,则这是一个关系数据库 API,在针对 InMemory 运行时将不起作用。提示

对于许多测试目的,这些差异无关紧要。但是,如果您想针对更像真正关系数据库的行为进行测试,请考虑使用 SQLite 内存模式。

话虽如此:如果您确实需要验证约束,请遵循文档的建议并在内存数据库中使用 Sqlite 代替您的集成测试。