首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带构造函数参数的MOQ SetupGet dbContext

带构造函数参数的MOQ SetupGet dbContext
EN

Stack Overflow用户
提问于 2020-10-28 09:51:22
回答 1查看 1.1K关注 0票数 1

Situation

在这里,我试图用MOQ为我的GroupService编写一些单元测试。

为了创建我的GroupService实例,我模拟了需要通过构造函数传递的4个接口。现在,在其中一个模拟(IGroupRepository)中,调用了一个名为Context的属性,我的想法是对这个属性进行SetupGet,只需返回一个虚假的GroupUser列表即可。但无论我尝试什么,我都会犯错。

代码语言:javascript
复制
public class GroupServiceTests
{
    private readonly GroupService _groupService;
    private readonly Mock<AppDbContext> _dbContext;
    private readonly Mock<IGroupRepository> _groupRepository;
    private readonly Mock<IComponentService> _componentService;
    private readonly Mock<IUserContextService> _userContextService;
    private readonly Mock<IModelEntityMapper<Group, Core.DbContexts.Entities.Group>> _mapper;

    public GroupServiceTests()
    {
        var groupUsersMock = CreateDbSetMock(GetFakeListOfGroupUsers());
        _dbContext = new Mock<AppDbContext>(new DbContextOptions<AppDbContext>());
        _dbContext.SetupGet(x => x.GroupUser).Returns(groupUsersMock.Object);

        _groupRepository = new Mock<IGroupRepository>();
        _groupRepository.SetupGet(repo => repo.Context).Returns(_dbContext.Object);

        _componentService = new Mock<IComponentService>();
        _userContextService = new Mock<IUserContextService>();
        _mapper = new Mock<IModelEntityMapper<Group, Core.DbContexts.Entities.Group>>();

        _groupService = new GroupService(_groupRepository.Object, _componentService.Object, _userContextService.Object, _mapper.Object);
    }
}

GroupService中,这一行被称为:

代码语言:javascript
复制
// _repository reffers to IGroupRepository
userIdsForContextReset.AddRange(_repository.Context.GroupUser.Where(x => groupIds.Contains(x.GroupId)).Select(x => x.UserId));

GroupRepositoryEntityRepository看起来是这样的:

代码语言:javascript
复制
public interface IGroupRepository : IEntityRepository<AppDbContext, Group>
{
    List<GroupPermission> GetInheritedGroupPermissions(int groupId);
}

public class GroupRepository : EntityRepository<AppDbContext, Group>, IGroupRepository
{
    public GroupRepository(AppDbContext dbContext) : base(dbContext)
    {
    }

    public List<GroupPermission> GetInheritedGroupPermissions(int groupId)
    {
        // Removed for brevity
    }
}
代码语言:javascript
复制
public class EntityRepository<TDbContext, TEntity> : EntityRepository<TDbContext, TEntity, int>, IEntityRepository<TDbContext, TEntity>
     where TDbContext : DbContext
     where TEntity : class, IEntity<int>
{
    public EntityRepository(TDbContext dbContext) : base(dbContext)
    {
    }
}
代码语言:javascript
复制
public class EntityRepository<TDbContext, TEntity, TId> : IEntityRepository<TDbContext, TEntity, TId>
     where TDbContext : DbContext
     where TEntity : class, IEntity<TId>
     where TId : IComparable
{
    public EntityRepository(TDbContext context)
    {
        Context = context;
    }

    public TDbContext Context { get; }
}

最后但并非最不重要的是,AppDbContextSqlDbContext

代码语言:javascript
复制
public class AppDbContext : Shared.DbContexts.SqlDbContext
{
    public virtual DbSet<GroupUser> GroupUser { get; set; }

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }
}
代码语言:javascript
复制
public class SqlDbContext : DbContext
{
    public SqlDbContext(DbContextOptions options) : base(options)
    {
        ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        ChangeTracker.StateChanged += ChangeTracker_StateChanged;
    }
}

误差

我所得到的错误在构造函数第一行的SqlDbContext中,并说明如下:

System.InvalidOperationException:“没有为此DbContext配置数据库提供程序。可以通过覆盖DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。如果使用了AddDbContext,还可以确保DbContext类型在构造函数中接受DbContextOptions对象,并将其传递给DbContext的基本构造函数。”

我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-29 02:29:41

当您模拟一个实现时,它使用与提供的参数相匹配的构造函数创建对象;它运行该代码。此外,任何不能被模仿的东西(不是虚拟的或抽象的)都会按原样运行。在这种情况下,您传递的是DbContextOptions,并且没有指定提供程序,有些东西需要这样做。

这可能是一个固执己见的话题,但是要解决您的问题,有许多方法可以做到:

  1. 向DbContext添加无参数构造函数以进行测试。我不建议这样做,因为我遵循的是不为测试改变你的口头禅。
  2. 使用内存中的提供程序;EF核心内存数据库提供程序SQLite EF核心数据库提供者是我使用过的两个。它们确实有局限性,但对于OP的使用可能还不错,并介绍了Microsofts关于如何不使用嘲弄DbContext的注意事项。
  3. 使用现有的库,如EntityFrameworkCore.Testing (免责声明,我是作者),它将扩展内存提供程序以解决它们的局限性。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64570307

复制
相关文章

相似问题

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