【问题标题】:Moq Unsupported expression起订量 不支持的表达式
【发布时间】:2021-10-25 12:13:42
【问题描述】:

我在关注this documentation

我正在尝试构建一个能够模拟 DbContext 和服务的测试项目。

我的 DbContext:

public class ProjectDbContext : DbContext
{
    public DbSet<Item> Items { get; set; }

    public ProjectDbContext(DbContextOptions<ProjectDbContext> opt) : base(opt)
    {}
}

可序列化:

public interface ISerializable 
{      
    Task<bool> SaveChangesAsync();
    bool SaveChanges();
}

基础服务:

public class BaseService : ISerializable
{
    protected readonly ProjectDbContext context;

    public BaseService(ProjectDbContext context)
    {
        context = context;   
    }
    
    public async Task<bool> SaveChangesAsync()
    {
        var result = await context.SaveChangesAsync();
        return result >= 0;
    }

    public bool SaveChanges()
    {
        var result = context.SaveChanges();
        return result >= 0;
    }
}

我的物品服务界面:

public interface IItemsService : ISerializable
{
    Item GetById(Guid id);
}

物品服务:

public class ItemsService : BaseService, IItemsService
{

    public ItemsService(ProjectDbContext context)
        : base(context)
    { }

    public Item GetById(Guid id)
    {
        return context.Items.FirstOrDefault(x => x.Id == id);
    }
}

我的测试:

public class ItemTest
{
    private readonly Mock<DbSet<Item>> _mockSet = new Mock<DbSet<Item>>();
    private Mock<ProjectDbContext> _mockContext;

    public ItemTest()
    {
        _mockContext = new Mock<ProjectDbContext >();
        _mockContext.Setup(m => m.Items).Returns(_mockSet.Object);
    }

    [Fact]
    public void GetById_ShouldReturnItemWhenItemExists()
    {
        // Service
        var repository = new ItemsService(_mockContext.Object);

        // Arrange
        var itemId = Guid.NewGuid();

        // Act
        var item = repository.GetById(itemId, CancellationToken.None);

        // Assert
        Assert.Equal(itemId, item.Id);
    }
}

错误信息:

System.NotSupportedException 不支持的表达式:m => m.Items 不可覆盖的成员(此处:ProjectDbContext.get_Items)不得用于设置/验证表达式。 在 C:\projects\moq4\src\Moq\Guard.cs:line 99 中的 Moq.Guard.IsOverridable(MethodInfo 方法,表达式表达式) 在 C:\projects\moq4\src\Moq\InvocationShape.cs: 84 中的 Moq.InvocationShape..ctor(LambdaExpression 表达式,MethodInfo 方法,IReadOnlyList'1 参数,布尔精确通用类型参数,布尔skipMatcherInitialization,布尔allowNonOverridable) 在 Moq.ExpressionExtensions.g__Split|5_0(表达式 e、Expression& r、InvocationShape& p、布尔赋值、布尔 allowNonOverridableLastProperty)在 C:\projects\moq4\src\Moq\ExpressionExtensions.cs:324 行 在 C:\projects\moq4\src\Moq\ExpressionExtensions.cs:line 149 中的 Moq.ExpressionExtensions.Split(LambdaExpression 表达式,布尔 allowNonOverridableLastProperty) 在 C:\projects\moq4\src\Moq\Mock.cs:line 601 中的 Moq.Mock.SetupRecursive[TSetup](Mock mock, LambdaExpression 表达式, Func'4 setupLast, Boolean allowNonOverridableLastProperty) 在 C:\projects\moq4\src\Moq\Mock.cs:line 505 中的 Moq.Mock.Setup(Mock mock, LambdaExpression 表达式, Condition 条件) 在 C:\projects\moq4\src\Moq\Mock`1.cs:line 454 中的 Moq.Mock'1.Setup[TResult](Expression'1 表达式) 在 ....\ItemTest.cs:line 20 中的 ItemTest.ctor() 处

错误显示以下行不可覆盖:

_mockContext.Setup(m => m.Items).Returns(_mockSet.Object);

我尝试将 Items DbSet 设为 virtual 成员。然后我开始得到:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException 无法实例化类的代理:....ProjectDbContext。

添加无参数构造函数会引发另一个异常,这让我觉得我做错了什么。对于我的问题,我将不胜感激。

【问题讨论】:

标签: c# unit-testing .net-core moq xunit


【解决方案1】:

添加一个无参数构造函数对我有用,但是您需要添加一个新的“设置行”,您可以在其中模拟您的“项目”:

public DbSet<Item> GetItems() {
//your logic
}

并添加

   _mockSet.Setup(i => i).Returns(GetItems());

到您的测试构造函数。

【讨论】:

  • 我已经试过了。它会导致 GetById 方法抛出 NullRefEx。在 Microsoft.EntityFrameworkCore.ModelExtensions.FindEntityType(IModel 模型,类型类型) 在 Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityType() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.CheckState() 在 Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityQueryable() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.System.Linq.IQueryable。 get_Provider()
  • 回复已编辑的答案:这似乎是一种解决方法,而不是一个强大的解决方案。
猜你喜欢
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 2019-08-31
  • 2020-11-30
  • 1970-01-01
  • 2017-06-07
相关资源
最近更新 更多