EF Core:使用 InMemory 数据库进行测试具有不一致的行为
EF Core : Testing with InMemory Database has inconsistent behavior
我正在使用 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);
}
有人知道这件事吗?
提前致谢,
您正在多个测试中重复使用相同的数据库上下文。测试可以 运行 并行进行。因此,当使用相同的数据库上下文测试时,可能会影响彼此的结果。为避免这种情况,您需要通过让测试使用干净的数据库上下文来隔离测试:
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.
我正在使用 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);
}
有人知道这件事吗?
提前致谢,
您正在多个测试中重复使用相同的数据库上下文。测试可以 运行 并行进行。因此,当使用相同的数据库上下文测试时,可能会影响彼此的结果。为避免这种情况,您需要通过让测试使用干净的数据库上下文来隔离测试:
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.