EF Core 查询在真实数据库中运行良好,但测试失败
EF Core query working fine with real DB but the test fails
我正在使用 C#、.NET Core 2.2 和 Xunit 框架。
以下代码,方法 "GetTopFive",当我在 Web API 控制器中执行它并连接到真实数据库(SQL Server 2017)时工作正常。
public class MovieRepository : IMovieRepository
{
private readonly MovieDbContext _moviesDbContext;
public MovieRepository(MovieDbContext moviesDbContext)
{
_moviesDbContext = moviesDbContext;
}
public IEnumerable<Movie> GetAll()
{
return _moviesDbContext.Movies;
}
public IEnumerable<MovieRating> GetTopFive()
{
var result = _moviesDbContext.Movies.Include(x => x.Ratings)
.Select(x => new MovieRating
{
Id = x.Id,
Title = x.Title,
Average = x.Ratings.Average(y => y.RatingValue)
}).OrderByDescending(x => x.Average).ThenBy(x => x.Title).Take(5).ToList();
return result;
}
}
但是当我 运行 测试时我得到了这个错误:
Message: System.InvalidOperationException : Sequence contains no elements
这是测试代码,我用的是内存DB:
public class MovieRepositoryTest : IClassFixture<MovieSeedDataFixture>
{
private readonly IMovieRepository _sut;
private readonly MovieFilters _filters;
public MovieRepositoryTest(MovieSeedDataFixture fixture)
{
_sut = new MovieRepository(fixture.MovieContext);
_filters = new MovieFilters { Genre = "Action" };
}
[Fact]
public void GetTopFiveMovies_WhenCalled_ReturnsFiveMovies()
{
//Act
var movies = _sut.GetTopFive();
//Assert
Assert.Equal(5, movies.Count());
}
}
如果我通过删除 "OrderByDescending" 来更改存储库,它会起作用,但这不是我需要的结果:
public IEnumerable<MovieRating> GetTopFive()
{
var result = _moviesDbContext.Movies.Include(x => x.Ratings)
.Select(x => new MovieRating
{
Id = x.Id,
Title = x.Title,
Average = x.Ratings.Average(y => y.RatingValue)
}).Take(5).ToList();
return result;
}
这是夹具 class,显然有数据:
public class MovieSeedDataFixture : IDisposable
{
public MovieDbContext MovieContext { get; }
public MovieSeedDataFixture()
{
var databaseName = "MovieListDatabase_" + DateTime.Now.ToFileTimeUtc();
var options = new DbContextOptionsBuilder<MovieDbContext>()
.UseInMemoryDatabase(databaseName)
.Options;
MovieContext = new MovieDbContext(options);
// Load movies
MovieContext.Movies.Add(new Movie { Id = 1, Title = "John Wick", YearOfRelease = 2015, Genre = "Action", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 2, Title = "John Wick: Chapter 2", YearOfRelease = 2017, Genre = "Action", RunningTime = 130 });
MovieContext.Movies.Add(new Movie { Id = 3, Title = "Terminator 6", YearOfRelease = 2019, Genre = "Science Fiction/Action", RunningTime = 110 });
MovieContext.Movies.Add(new Movie { Id = 4, Title = "The Saint", YearOfRelease = 2017, Genre = "Action", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 5, Title = "The Interview", YearOfRelease = 2014, Genre = "Action/Comedy", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 6, Title = "Mr. & Mrs. Smith", YearOfRelease = 2005, Genre = "Crime/Thriller", RunningTime = 115 });
MovieContext.Movies.Add(new Movie { Id = 7, Title = "Fast & Furious 8", YearOfRelease = 2017, Genre = "Crime/Action", RunningTime = 125 });
MovieContext.Movies.Add(new Movie { Id = 8, Title = "Fast & Furious 1", YearOfRelease = 2001, Genre = "Crime/Action", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 9, Title = "Jason Bourne", YearOfRelease = 2016, Genre = "Action", RunningTime = 135 });
MovieContext.Movies.Add(new Movie { Id = 10, Title = "Iron Man 3", YearOfRelease = 2013, Genre = "Science Fiction/Action", RunningTime = 110 });
// Load Users
MovieContext.Users.Add(new User { Id = 1, FirstName = "John", Lastname = "Doe" });
MovieContext.Users.Add(new User { Id = 2, FirstName = "Jane", Lastname = "Doe" });
// Load Ratings
MovieContext.Ratings.Add(new Rating { Id = 1, MovieId = 1, UserId = 1, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 2, MovieId = 1, UserId = 2, RatingValue = 5 });
MovieContext.Ratings.Add(new Rating { Id = 3, MovieId = 2, UserId = 1, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 4, MovieId = 2, UserId = 2, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 5, MovieId = 3, UserId = 1, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 6, MovieId = 3, UserId = 2, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 7, MovieId = 4, UserId = 1, RatingValue = 3 });
MovieContext.Ratings.Add(new Rating { Id = 8, MovieId = 4, UserId = 2, RatingValue = 3 });
MovieContext.Ratings.Add(new Rating { Id = 9, MovieId = 5, UserId = 1, RatingValue = 2 });
MovieContext.Ratings.Add(new Rating { Id = 10, MovieId = 5, UserId = 2, RatingValue = 2 });
MovieContext.Ratings.Add(new Rating { Id = 11, MovieId = 6, UserId = 1, RatingValue = 1 });
MovieContext.Ratings.Add(new Rating { Id = 12, MovieId = 6, UserId = 2, RatingValue = 1 });
MovieContext.SaveChanges();
}
public void Dispose()
{
MovieContext.Dispose();
}
}
对我为什么会出现这个错误有什么帮助吗?
谢谢
问题与
有关
Average = x.Ratings.Average(y => y.RatingValue)
因为并非所有电影都有评级,Average()
将在空序列上抛出该异常。
如果你期待没有评级的电影,你可以使用三元表达式:
Average = x.Ratings.Any() ? x.Ratings.Average(y => y.RatingValue) : 0 // or null depending on your model
我正在使用 C#、.NET Core 2.2 和 Xunit 框架。
以下代码,方法 "GetTopFive",当我在 Web API 控制器中执行它并连接到真实数据库(SQL Server 2017)时工作正常。
public class MovieRepository : IMovieRepository
{
private readonly MovieDbContext _moviesDbContext;
public MovieRepository(MovieDbContext moviesDbContext)
{
_moviesDbContext = moviesDbContext;
}
public IEnumerable<Movie> GetAll()
{
return _moviesDbContext.Movies;
}
public IEnumerable<MovieRating> GetTopFive()
{
var result = _moviesDbContext.Movies.Include(x => x.Ratings)
.Select(x => new MovieRating
{
Id = x.Id,
Title = x.Title,
Average = x.Ratings.Average(y => y.RatingValue)
}).OrderByDescending(x => x.Average).ThenBy(x => x.Title).Take(5).ToList();
return result;
}
}
但是当我 运行 测试时我得到了这个错误:
Message: System.InvalidOperationException : Sequence contains no elements
这是测试代码,我用的是内存DB:
public class MovieRepositoryTest : IClassFixture<MovieSeedDataFixture>
{
private readonly IMovieRepository _sut;
private readonly MovieFilters _filters;
public MovieRepositoryTest(MovieSeedDataFixture fixture)
{
_sut = new MovieRepository(fixture.MovieContext);
_filters = new MovieFilters { Genre = "Action" };
}
[Fact]
public void GetTopFiveMovies_WhenCalled_ReturnsFiveMovies()
{
//Act
var movies = _sut.GetTopFive();
//Assert
Assert.Equal(5, movies.Count());
}
}
如果我通过删除 "OrderByDescending" 来更改存储库,它会起作用,但这不是我需要的结果:
public IEnumerable<MovieRating> GetTopFive()
{
var result = _moviesDbContext.Movies.Include(x => x.Ratings)
.Select(x => new MovieRating
{
Id = x.Id,
Title = x.Title,
Average = x.Ratings.Average(y => y.RatingValue)
}).Take(5).ToList();
return result;
}
这是夹具 class,显然有数据:
public class MovieSeedDataFixture : IDisposable
{
public MovieDbContext MovieContext { get; }
public MovieSeedDataFixture()
{
var databaseName = "MovieListDatabase_" + DateTime.Now.ToFileTimeUtc();
var options = new DbContextOptionsBuilder<MovieDbContext>()
.UseInMemoryDatabase(databaseName)
.Options;
MovieContext = new MovieDbContext(options);
// Load movies
MovieContext.Movies.Add(new Movie { Id = 1, Title = "John Wick", YearOfRelease = 2015, Genre = "Action", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 2, Title = "John Wick: Chapter 2", YearOfRelease = 2017, Genre = "Action", RunningTime = 130 });
MovieContext.Movies.Add(new Movie { Id = 3, Title = "Terminator 6", YearOfRelease = 2019, Genre = "Science Fiction/Action", RunningTime = 110 });
MovieContext.Movies.Add(new Movie { Id = 4, Title = "The Saint", YearOfRelease = 2017, Genre = "Action", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 5, Title = "The Interview", YearOfRelease = 2014, Genre = "Action/Comedy", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 6, Title = "Mr. & Mrs. Smith", YearOfRelease = 2005, Genre = "Crime/Thriller", RunningTime = 115 });
MovieContext.Movies.Add(new Movie { Id = 7, Title = "Fast & Furious 8", YearOfRelease = 2017, Genre = "Crime/Action", RunningTime = 125 });
MovieContext.Movies.Add(new Movie { Id = 8, Title = "Fast & Furious 1", YearOfRelease = 2001, Genre = "Crime/Action", RunningTime = 120 });
MovieContext.Movies.Add(new Movie { Id = 9, Title = "Jason Bourne", YearOfRelease = 2016, Genre = "Action", RunningTime = 135 });
MovieContext.Movies.Add(new Movie { Id = 10, Title = "Iron Man 3", YearOfRelease = 2013, Genre = "Science Fiction/Action", RunningTime = 110 });
// Load Users
MovieContext.Users.Add(new User { Id = 1, FirstName = "John", Lastname = "Doe" });
MovieContext.Users.Add(new User { Id = 2, FirstName = "Jane", Lastname = "Doe" });
// Load Ratings
MovieContext.Ratings.Add(new Rating { Id = 1, MovieId = 1, UserId = 1, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 2, MovieId = 1, UserId = 2, RatingValue = 5 });
MovieContext.Ratings.Add(new Rating { Id = 3, MovieId = 2, UserId = 1, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 4, MovieId = 2, UserId = 2, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 5, MovieId = 3, UserId = 1, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 6, MovieId = 3, UserId = 2, RatingValue = 4 });
MovieContext.Ratings.Add(new Rating { Id = 7, MovieId = 4, UserId = 1, RatingValue = 3 });
MovieContext.Ratings.Add(new Rating { Id = 8, MovieId = 4, UserId = 2, RatingValue = 3 });
MovieContext.Ratings.Add(new Rating { Id = 9, MovieId = 5, UserId = 1, RatingValue = 2 });
MovieContext.Ratings.Add(new Rating { Id = 10, MovieId = 5, UserId = 2, RatingValue = 2 });
MovieContext.Ratings.Add(new Rating { Id = 11, MovieId = 6, UserId = 1, RatingValue = 1 });
MovieContext.Ratings.Add(new Rating { Id = 12, MovieId = 6, UserId = 2, RatingValue = 1 });
MovieContext.SaveChanges();
}
public void Dispose()
{
MovieContext.Dispose();
}
}
对我为什么会出现这个错误有什么帮助吗? 谢谢
问题与
有关Average = x.Ratings.Average(y => y.RatingValue)
因为并非所有电影都有评级,Average()
将在空序列上抛出该异常。
如果你期待没有评级的电影,你可以使用三元表达式:
Average = x.Ratings.Any() ? x.Ratings.Average(y => y.RatingValue) : 0 // or null depending on your model