为了账号安全,请及时绑定邮箱和手机立即绑定

模拟 EF 核心 dbcontext 和 dbset

模拟 EF 核心 dbcontext 和 dbset

C#
慕尼黑5688855 2022-07-23 17:34:08
我正在使用 ASP.NET Core 2.2、EF Core 和 MOQ。当我运行测试时,我收到此错误:消息:System.NotSupportedException:非虚拟(在 VB 中可覆盖)成员上的设置无效: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;    }  }这是我的数据库上下文,带有MoviedbSet:public class MovieDbContext: DbContext{    public MovieDbContext(DbContextOptions<MovieDbContext> options) : base(options)    {    }    public DbSet<Movie> Movies { get; set; }}
查看完整描述

3 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

我看到您DbContext在MovieRepository. 因此,不使用模拟,使用 EF CoreInMemory数据库将是您的绝佳选择。这也将降低复杂性。


编写您的GetAllTest()方法如下:


[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.InMemorynuget包如下:


安装包 Microsoft.EntityFrameworkCore.InMemory


查看完整回答
反对 回复 2022-07-23
?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

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


//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


//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.4 版本开始支持 AutoMapper

  • 从 1.1.0 版本开始支持 DbQuery

  • 从 3.0.0 版本开始支持 EF Core 3.0


查看完整回答
反对 回复 2022-07-23
?
FFIVE

TA贡献1797条经验 获得超6个赞

使用Moq.EntityFrameworkCore包。


这很简单:


var myDbContextMock = new Mock<MyDbContext>();

IList<Entity> entities = new List<Entity>() { new Entity(), new Entity() };

myDbContextMock.Setup(x => x.Entities).ReturnsDbSet(entities);


查看完整回答
反对 回复 2022-07-23
  • 3 回答
  • 0 关注
  • 96 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信