gpt4 book ai didi

c# - 使用 EF Core 和内存数据库进行单元测试

转载 作者:太空狗 更新时间:2023-10-30 00:29:34 25 4
gpt4 key购买 nike

我正在使用 ASP.NET Core 2.2、EF Core 和 MOQ。正如您在下面的代码中看到的,我有两个测试,并且一起运行,两个数据库名称均为“MovieListDatabase”,我在其中一个测试中遇到错误并显示此消息:

Message: System.ArgumentException : An item with the same key has already 
been added. Key: 1

如果我分别运行每一个,它们都会通过。

而且,在两个测试中使用不同的数据库名称,例如“MovieListDatabase1”和“MovieListDatabase2”,并同时运行这两个测试,它再次通过。

我有两个问题:为什么会这样?以及如何重构我的代码以在两个测试中重新使用内存数据库并使我的测试看起来更干净一些?

 public class MovieRepositoryTest
{
[Fact]
public void GetAll_WhenCalled_ReturnsAllItems()
{

var options = new DbContextOptionsBuilder<MovieDbContext>()
.UseInMemoryDatabase(databaseName: "MovieListDatabase")
.Options;

// Insert seed data into the database using one instance of the context
using (var context = new MovieDbContext(options))
{
context.Movies.Add(new Movie { Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" });
context.Movies.Add(new Movie { Id = 2, Title = "Movie 2", YearOfRelease = 2018, Genre = "Action" });
context.Movies.Add(new Movie { Id = 3, Title = "Movie 3", YearOfRelease = 2019, Genre = "Action" });
context.SaveChanges();
}

// Use a clean instance of the context to run the test
using (var context = new MovieDbContext(options))
{
var sut = new MovieRepository(context);
//Act
var movies = sut.GetAll();

//Assert
Assert.Equal(3, movies.Count());
}
}

[Fact]
public void Search_ValidTitlePassed_ReturnsOneMovie()
{
var filters = new MovieFilters { Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" };

var options = new DbContextOptionsBuilder<MovieDbContext>()
.UseInMemoryDatabase(databaseName: "MovieListDatabase")
.Options;

// Insert seed data into the database using one instance of the context
using (var context = new MovieDbContext(options))
{
context.Movies.Add(new Movie { Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" });
context.Movies.Add(new Movie { Id = 2, Title = "Movie 2", YearOfRelease = 2018, Genre = "Action" });
context.Movies.Add(new Movie { Id = 3, Title = "Movie 3", YearOfRelease = 2019, Genre = "Action" });
context.SaveChanges();
}

// Use a clean instance of the context to run the test
using (var context = new MovieDbContext(options))
{
var sut = new MovieRepository(context);

//Act
//var movies = _sut.Search(_filters);
var movies = sut.Search(filters);

//Assert
Assert.Single(movies);
}
}
}

这是存储库类

 public class MovieRepository: IMovieRepository
{
private readonly MovieDbContext _moviesDbContext;
public MovieRepository(MovieDbContext moviesDbContext)
{
_moviesDbContext = moviesDbContext;
}

public IEnumerable<Movie> GetAll()
{
return _moviesDbContext.Movies;
}

public IEnumerable<Movie> Search(MovieFilters filters)
{
var title = filters.Title.ToLower();
var genre = filters.Genre.ToLower();
return _moviesDbContext.Movies.Where( p => (p.Title.Trim().ToLower().Contains(title) | string.IsNullOrWhiteSpace(p.Title))
& (p.Genre.Trim().ToLower().Contains(genre) | string.IsNullOrWhiteSpace(p.Genre))
& (p.YearOfRelease == filters.YearOfRelease | filters.YearOfRelease == null)
);
}
}

谢谢

最佳答案

看起来您可能需要 class fixture .

When to use: when you want to create a single test context and share it among all the tests in the class, and have it cleaned up after all the tests in the class have finished.

创建一个单独的类来设置您的测试将共享的任何数据,并在测试运行完成时清理它。

public class MovieSeedDataFixture : IDisposable
{
public MovieDbContext MovieContext { get; private set; } = new MovieDbContext();

public MovieSeedDataFixture()
{
MovieContext.Movies.Add(new Movie { Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" });
MovieContext.Movies.Add(new Movie { Id = 2, Title = "Movie 2", YearOfRelease = 2018, Genre = "Action" });
MovieContext.Movies.Add(new Movie { Id = 3, Title = "Movie 3", YearOfRelease = 2019, Genre = "Action" });
MovieContext.SaveChanges();
}

public void Dispose()
{
MovieContext.Dispose();
}
}

然后通过扩展 IClassFixture<T> 在您的测试中使用它界面。

public class UnitTests : IClassFixture<MovieSeedDataFixture>
{
MovieSeedDataFixture fixture;

public UnitTests(MovieSeedDataFixture fixture)
{
this.fixture = fixture;
}

[Fact]
public void TestOne()
{
// use fixture.MovieContext in your tests

}
}

关于c# - 使用 EF Core 和内存数据库进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54264787/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com