我正在使用InMemory数据库在ASP .NET Core Web API应用程序中测试我的存储库层。 因此,在几次测试中,我都设置了数据。但是,使用相同的代码,当我运行测试时,有时会存在数据,有时却没有。我不明白为什么。
我正在使用XUnit测试框架。
这是我的考试:
public class UserRepositoryTest
{
private ApplicationDbContext context;
void setup()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "ApplicationDatabase")
.Options;
this.context = new ApplicationDbContext(options);
this.context.Database.EnsureDeleted();
}
[Fact]
void GetUserByUsernameTest()
{
this.setup();
// Given
var manager = new User {Username = "Ombrelin", Email = "test@test.fr"};
context.Users.Add(manager);
context.SaveChanges();
// When
var repo = new UserRepository(context);
var user = repo.GetUserByUsername("Ombrelin");
// Then
Assert.Equal("Ombrelin", user.Username);
}
[Fact]
void FindUsersByUsernameContainsTest()
{
this.setup();
// Given
var manager1 = new User {Username = "Arsène", Email = "test@test.fr"};
var manager2 = new User {Username = "Jean Michel", Email = "test@test.fr"};
context.Users.Add(manager1);
context.Users.Add(manager2);
context.SaveChanges();
// When
var repo = new UserRepository(context);
var users = repo.findUsersByUsernameContains("Ars");
// Then
Assert.Single(users);
}
有人对此有任何线索吗?
预先感谢
答案 0 :(得分:1)
您正在多个测试中重用同一数据库上下文。测试可以并行运行。因此,当使用相同的数据库时,上下文测试可能会影响彼此的结果。为避免这种情况,您需要通过允许测试使用干净的数据库上下文来隔离测试:
public class UserRepositoryTest
{
[Fact]
public void GetUserByUsernameTest()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: $"ApplicationDatabase{Guid.NewGuid()}")
.Options;
using(var context = new ApplicationDbContext(options))
{
// Given
var manager = new User { Username = "Ombrelin", Email = "test@test.fr" };
context.Users.Add(manager);
context.SaveChanges();
// When
var repo = new UserRepository(context);
var user = repo.GetUserByUsername("Ombrelin");
// Then
Assert.Equal("Ombrelin", user.Username);
}
}
}
通过向数据库名称添加唯一的ID,可以确保测试使用的是唯一的内存数据库。显然,这会使测试执行速度变慢。许多测试人员还使用不同的上下文来播种数据并执行测试:
public class UserRepositoryTest
{
[Fact]
public void GetUserByUsernameTestSeparateContexts()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: $"ApplicationDatabase{Guid.NewGuid()}")
.Options;
using (var context = new ApplicationDbContext(options))
{
// Given
var manager = new User { Username = "Ombrelin", Email = "test@test.fr" };
context.Users.Add(manager);
context.SaveChanges();
}
using (var context = new ApplicationDbContext(options))
{
// When
var repo = new UserRepository(context);
var user = repo.GetUserByUsername("Ombrelin");
// Then
Assert.Equal("Ombrelin", user.Username);
}
}
}
这使测试更加切合实际,因为作为数据种子的函数和使用数据的函数通常使用不同的上下文。还请记住,InMemoryProvider不是关系数据库。因此,它不支持实际数据库服务器的某些功能,例如参照完整性检查,TimeStamp,IsRowVersion等。有关详细信息,请参阅MS文档:here。