首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟EF核心dbset和dbset

模拟EF核心dbset和dbset
EN

Stack Overflow用户
提问于 2019-01-16 14:56:23
回答 6查看 78.3K关注 0票数 75

我正在使用ASP.NET核心2.2,EF核心和MOQ。当我运行测试时,我得到了以下错误:

消息: System.NotSupportedException :非虚拟(在VB中可覆盖)成员上的无效设置:x => x.Movies

我做错什么了?

代码语言:javascript
复制
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;
    }
  }

这是我的DB上下文,带有Movie dbSet:

代码语言:javascript
复制
public class MovieDbContext: DbContext
{
    public MovieDbContext(DbContextOptions<MovieDbContext> options) : base(options)
    {

    }

    public DbSet<Movie> Movies { get; set; }
}

以及要测试的方法GetAll的存储库:

代码语言:javascript
复制
 public class MovieRepository: IMovieRepository
{
    private readonly MovieDbContext _moviesDbContext;
    public MovieRepository(MovieDbContext moviesDbContext)
    {
        _moviesDbContext = moviesDbContext;
    }

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

回答 6

Stack Overflow用户

回答已采纳

发布于 2019-01-16 15:13:27

我看到你正在使用EF核心DbContext在你的MovieRepository。因此,使用EF InMemory数据库将是一个很好的选择,而不是使用模拟。这也将降低复杂性。

按照以下方式编写GetAllTest()方法:

代码语言:javascript
复制
[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(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))
        {
            MovieRepository movieRepository = new MovieRepository(context);
            List<Movies> movies == movieRepository.GetAll();

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

注意:不要忘记安装Microsoft.EntityFrameworkCore.InMemory nuget包,如下所示:

安装包Microsoft.EntityFrameworkCore.InMemory

有关更多详细信息:用InMemory进行测试

票数 169
EN

Stack Overflow用户

发布于 2019-12-19 10:14:32

为了节省您的时间,尝试使用我的Moq/nsub妓女扩展MockQueryable:https://github.com/romantitov/MockQueryable支持所有同步/异步操作

代码语言:javascript
复制
//1 - create a List<T> with test items
var users = new List<UserEntity>()
{
 new UserEntity,
 ...
};

//2 - build mock by extension
var mock = users.AsQueryable().BuildMock();

//3 - setup the mock as Queryable for Moq
_userRepository.Setup(x => x.GetQueryable()).Returns(mock.Object);

//3 - setup the mock as Queryable for NSubstitute
_userRepository.GetQueryable().Returns(mock);

DbSet也支持

代码语言:javascript
复制
//2 - build mock by extension
var mock = users.AsQueryable().BuildMockDbSet();

//3 - setup DbSet for Moq
var userRepository = new TestDbSetRepository(mock.Object);

//3 - setup DbSet for NSubstitute
var userRepository = new TestDbSetRepository(mock);

注:

  • 1.0.4ver支持的AutoMapper
  • 1.1.0ver支持的DbQuery
  • 3.0.0 ver支持的EF Core 3.0
票数 29
EN

Stack Overflow用户

发布于 2022-01-03 20:52:19

使用Moq.EntityFrameworkCore包。

它很简单,就像:

代码语言:javascript
复制
using Moq.EntityFrameworkCore;

var myDbContextMock = new Mock<MyDbContext>();
var entities = new List<Entity>() { new Entity(), new Entity() };
myDbContextMock.Setup(x => x.Entities).ReturnsDbSet(entities);
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54219742

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档