EF Core查询可以在真实数据库中正常工作,但测试失败

时间:2019-01-21 13:57:02

标签: c# entity-framework .net-core asp.net-core-webapi xunit.net

我正在使用C#、. NET Core 2.2和Xunit框架。

当我在Web API控制器中执行以下代码并将其连接到真实数据库(SQL Server 2017)时,以下代码即方法“ GetTopFive”可以正常工作。

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

这是测试代码,我使用内存数据库:

 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;
}

这是灯具类,显然有数据:

 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();
    }
}

有什么帮助我为什么会出现该错误? 谢谢

1 个答案:

答案 0 :(得分:1)

问题与

有关
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