模拟EF核心dbcontext和dbset [英] Mocking EF core dbcontext and dbset
问题描述
我正在使用ASP.NET Core 2.2,EF Core和MOQ.当我运行测试时,出现此错误:
I am using ASP.NET Core 2.2, EF Core and MOQ. When I run the test I am getting this error:
消息:System.NotSupportedException:在非虚拟(在VB中可重写)成员上的无效设置:x => x.Movies
Message: System.NotSupportedException : Invalid setup on a non-virtual (overridable in VB) member: x => x.Movies
我做错了什么?
public class MovieRepositoryTest
{
private readonly MovieRepository _sut;
public MovieRepositoryTest()
{
var moviesMock = CreateDbSetMock(GetFakeListOfMovies());
var mockDbContext = new Mock<MovieDbContext>();
mockDbContext.Setup(x => x.Movies).Returns(moviesMock.Object);
_sut = new MovieRepository(mockDbContext.Object);
}
[Fact]
public void GetAll_WhenCalled_ReturnsAllItems()
{
//Act
var items = _sut.GetAll();
//Assert
Assert.Equal(3, items.Count());
}
private IEnumerable<Movie> GetFakeListOfMovies()
{
var movies = new List<Movie>
{
new Movie {Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action"},
new Movie {Id = 2, Title = "Movie 2", YearOfRelease = 2018, Genre = "Action"},
new Movie {Id = 3, Title = "Movie 3", YearOfRelease = 2019, Genre = "Action"}
};
return movies;
}
private static Mock<DbSet<T>> CreateDbSetMock<T>(IEnumerable<T> elements) where T : class
{
var elementsAsQueryable = elements.AsQueryable();
var dbSetMock = new Mock<DbSet<T>>();
dbSetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(elementsAsQueryable.Provider);
dbSetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(elementsAsQueryable.Expression);
dbSetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(elementsAsQueryable.ElementType);
dbSetMock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(elementsAsQueryable.GetEnumerator());
return dbSetMock;
}
}
这是我的数据库上下文,具有Movie
dbSet:
And this is my DB Context, with the Movie
dbSet:
public class MovieDbContext: DbContext
{
public MovieDbContext(DbContextOptions<MovieDbContext> options) : base(options)
{
}
public DbSet<Movie> Movies { get; set; }
}
以及要测试的方法GetAll
的存储库:
And the Repository with the method GetAll
to be tested:
public class MovieRepository: IMovieRepository
{
private readonly MovieDbContext _moviesDbContext;
public MovieRepository(MovieDbContext moviesDbContext)
{
_moviesDbContext = moviesDbContext;
}
public IEnumerable<Movie> GetAll()
{
return _moviesDbContext.Movies;
}
}
推荐答案
我看到您在MovieRepository
中使用EF核心DbContext
.因此,对于您而言,使用EF Core InMemory
数据库将是一个不错的选择,而不是使用模拟.这也将降低复杂性.
I see you are using EF core DbContext
in your MovieRepository
. So instead of using mock, Using EF Core InMemory
database will be a great option for you. This will also reduce the complexity.
编写您的GetAllTest()
方法,如下所示:
Write your GetAllTest()
method as follows:
[Fact]
public void GetAllTest()
{
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(nnew 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))
{
MovieRepository movieRepository = new MovieRepository(context);
List<Movies> movies == movieRepository.GetAll()
Assert.Equal(3, movies.Count);
}
}
注意:不要忘记按以下方式安装Microsoft.EntityFrameworkCore.InMemory
nuget软件包:
Note: Don't forget to install Microsoft.EntityFrameworkCore.InMemory
nuget package as follows:
安装软件包Microsoft.EntityFrameworkCore.InMemory
Install-Package Microsoft.EntityFrameworkCore.InMemory
有关更多详细信息:使用InMemory测试
这篇关于模拟EF核心dbcontext和dbset的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!