[英]Entity Framework Core Unique Index testing
我有一个模型课:
public class Work
{
public long Id { get; set; }
[Required]
public string Name { get; set; }
}
我希望这个Work.Name
将是唯一的,所以我定义了DbContext
:
public class MyDbContext : DbContext
{
public MyDbContext () : base() { }
public MyDbContext (DbContextOptions<MyDbContext > options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Work>(entity =>
entity.HasIndex(e => e.Name).IsUnique()
);
}
public DbSet<Work> Works { get; set; }
}
我想测试一下,所以我要进行如下测试:
[Fact]
public void Post_InsertDuplicateWork_ShouldThrowException()
{
var work = new Work
{
Name = "Test Work"
};
using (var context = new MyDbContext (options))
{
context.Works.Add(work);
context.SaveChanges();
}
using (var context = new MyDbContext (options))
{
context.Works.Add(work);
context.SaveChanges();
}
using (var context = new MyDbContext (options))
{
Assert.Equal(1, context.Works.Count());
}
}
( option
对象包含InMemoryDatabase
设置)
我真的不知道要检查什么,但是测试在Assert
而不是第二个SaveChanges()
失败。 数据库( context
)包含两个具有相同Name
对象。
我遍历了所有相关问题,但没有看到任何人回答我所问的问题。
正如其他人指出的那样,InMemory数据库提供程序忽略了所有可能的约束。
我的建议是,将Sqlite提供程序与“内存中”功能一起使用,这将为重复的唯一键引发异常。
public MyDbContext CreateSqliteContext()
{
var connectionString =
new SqliteConnectionStringBuilder { DataSource = ":memory:" }.ToString();
var connection = new SqliteConnection(connectionString);
var options = new DbContextOptionsBuilder<MyDbContext>().UseSqlite(connection);
return new MyDbContext(options);
}
private void Insert(Work work)
{
using (var context = CreateSqliteContext())
{
context.Works.Add(work);
context.SaveChanges();
}
}
[Fact]
public void Post_InsertDuplicateWork_ShouldThrowException()
{
var work1 = new Work { Name = "Test Work" };
var work2 = new Work { Name = "Test Work" };
Insert(work1);
Action saveDuplicate = () => Insert(work2);
saveDuplicate.Should().Throw<DbUpdateException>(); // Pass Ok
}
测试失败,因为第二个SaveChanges()
将从数据库中引发异常,该异常告诉您不能添加另一个项目,因为它已经包含具有该Name
的对象。
唯一的约束不会默默地强制执行。 相反,尝试添加重复值将在您尝试执行此操作时引发异常。 这样一来,您就可以对它做出实际反应,而不是仅在事后注意它(当您看到尝试添加的数据不存在时)。
您可以使用Assert.Throws
进行测试:
[Fact]
public void Post_InsertDuplicateWork_ShouldThrowException()
{
var work = new Work
{
Name = "Test Work"
};
using (var context = new MyDbContext (options))
{
context.Works.Add(work);
context.SaveChanges();
}
using (var context = new MyDbContext (options))
{
context.Works.Add(work);
Assert.Throws<Exception>(() => context.SaveChanges());
}
}
您还可以在此处指定确切的异常(我不记得在那上面确切抛出了哪个异常),还可以将其分配给变量( Assert.Throws()
返回该异常)和验证异常消息,以确保这是您期望的确切异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.