C# asp.net核心数据库集成测试
我正在尝试在asp.netcore项目中设置数据库的集成测试。我使用代码优先的方法来创建数据库。 用于使用nudget软件包XUnit、FluentAssertions和NuniteStataPadTer3测试iam。 当我第一次运行测试时,测试通过了C# asp.net核心数据库集成测试,c#,database,integration-testing,C#,Database,Integration Testing,我正在尝试在asp.netcore项目中设置数据库的集成测试。我使用代码优先的方法来创建数据库。 用于使用nudget软件包XUnit、FluentAssertions和NuniteStataPadTer3测试iam。 当我第一次运行测试时,测试通过了 [Collection("Integration test collection")] public class BookServiceTest : IntegrationTestBase { [Fact] public void
[Collection("Integration test collection")]
public class BookServiceTest : IntegrationTestBase
{
[Fact]
public void CanCreateUser()
{
using (var context = GivenBPDContext())
{
var Book = new BookService(context);
Data.Database.Entities.Book book = Book.AddNewBook("test");
context.SaveChanges();
book.Id.Should().NotBe(0);
book.Name.Should().Be("test");
}
}
}
public class IntegrationTestBase
{
protected static BPDContext GivenBPDContext()
{
var context = new BPDContext(new DbContextOptionsBuilder().Options);
return context;
}
// i tried dropping the database here and it do not work
}
一个非常基本的逻辑测试
public class BookService
{
private BPDContext _context;
public BookService(BPDContext context)
{
_context = context;
}
public Book AddNewBook(string name)
{
var book = _context.Books
.FirstOrDefault(x => x.Name == name);
if (book == null)
{
book = _context.Books.Add(new Data.Database.Entities.Book
{
Name = name,
}).Entity;
}
return book;
}
}
第二次运行测试并更改正在测试的值时失败。我需要一种方法,在每次测试后删除数据库,然后运行
迁移以将数据库升级到正确的版本
下面是我如何设置数据库的。
startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<IBPDRepository, BPDRepository>();
services.AddDbContext<BPDContext>();
}
public class BPDContext:DbContext
{
public DbSet<Entities.Book> Books { get; set; }
public DbSet<Entities.User> User { get; set; }
public DbSet<Entities.Reviewer> Reviewer { get; set; }
public BPDContext(DbContextOptions options):base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//maybe put something in if its in testing mode
optionsBuilder.UseSqlServer("Server = (localdb)\\mssqllocaldb;Database = BookProjectDatabase;Trusted_Connection = True; ", options => options.MaxBatchSize(30));
optionsBuilder.EnableSensitiveDataLogging();
}
}
总之,我需要在每次测试运行之前删除数据库,然后用迁移更新数据库,最后执行单元。看一看。避免迁移的另一个选项是执行数据库快照/恢复。最后,您可以在每次测试之前启动一个新的,然后在事务之后调用它的Dispose方法,而不调用它的Complete方法。这将中止事务并将数据库回滚到运行测试之前的状态
删除数据库有点费力,可能会增加运行测试所需的时间。看一看。避免迁移的另一个选项是执行数据库快照/恢复。最后,您可以在每次测试之前启动一个新的,然后在事务之后调用它的Dispose方法,而不调用它的Complete方法。这将中止事务并将数据库回滚到运行测试之前的状态
删除数据库有点费力,可能会增加运行测试所需的时间。您可以使用InMemoryDbContext进行测试操作。通过InMemoryDbContext,您不必创建物理数据库;此外,您可以轻松处理它
[Collection("Integration test collection")]
public class BookServiceTest : IDisposible
{
private BDPContext _context;
public BookServiceTest()
{
DbContextOptions<BPDContext> options = new DbContextOptionsBuilder<BPDContext>()
.UseInMemoryDatabase(GetType().Name)
.Options;
_context = new BPDContext(options);
}
[Fact]
public void CanCreateUser()
{
var Book = new BookService(context);
Data.Database.Entities.Book book = Book.AddNewBook("test");
context.SaveChanges();
book.Id.Should().NotBe(0);
book.Name.Should().Be("test");
}
public void Dispose()
{
_context.Dispose();
}
}
您可以使用InMemoryDbContext进行测试操作。通过InMemoryDbContext,您不必创建物理数据库;此外,您可以轻松处理它
[Collection("Integration test collection")]
public class BookServiceTest : IDisposible
{
private BDPContext _context;
public BookServiceTest()
{
DbContextOptions<BPDContext> options = new DbContextOptionsBuilder<BPDContext>()
.UseInMemoryDatabase(GetType().Name)
.Options;
_context = new BPDContext(options);
}
[Fact]
public void CanCreateUser()
{
var Book = new BookService(context);
Data.Database.Entities.Book book = Book.AddNewBook("test");
context.SaveChanges();
book.Id.Should().NotBe(0);
book.Name.Should().Be("test");
}
public void Dispose()
{
_context.Dispose();
}
}
InMemoryDbContext更像是单元测试而不是集成测试。我在想这两种方法都可以使用,因为InMemoryDbContext运行测试的速度要快得多,但可能无法像其他方法那样解决所有问题。我想我得多读一些这方面的资料。感谢您的帮助。不过,InMemoryDbContext在单元测试期间很好;在集成测试期间,真实数据库应该更好。在这种情况下,我为您提供了一种可以更改测试方法的方法。您可以使用日期值创建图书名称,这样就可以确保它不会进入数据库。如果要确保AddNewBook在db中已存在时不保存,则可以创建相同的book aproach并将其保存在db中。保存更改后,您可以再次尝试将其添加到数据库中。然而,@Kit提供的Respawn在我看来更有用。我想我会尝试实现这两种方法。再次感谢您的帮助。InMemoryDbContext更像是单元测试而不是集成测试吗。我在想这两种方法都可以使用,因为InMemoryDbContext运行测试的速度要快得多,但可能无法像其他方法那样解决所有问题。我想我得多读一些这方面的资料。感谢您的帮助。不过,InMemoryDbContext在单元测试期间很好;在集成测试期间,真实数据库应该更好。在这种情况下,我为您提供了一种可以更改测试方法的方法。您可以使用日期值创建图书名称,这样就可以确保它不会进入数据库。如果要确保AddNewBook在db中已存在时不保存,则可以创建相同的book aproach并将其保存在db中。保存更改后,您可以再次尝试将其添加到数据库中。然而,@Kit提供的Respawn在我看来更有用。我想我会尝试实现这两种方法。再次感谢你的帮助。谢谢你的建议。重生成功了。谢谢你的建议。重生成功了。