模拟 dbset<T> 中方法返回 NotSupportedException 的情况

6

我正尝试模拟通用仓库中dbset的where子句,但不知道为什么会出现System.NotSupported 异常。由于我对Mocking很新,所以不知道发生这种情况的原因。

private List<StubEntity> _data;
private Repository<StubEntity> _repository;

[TestInitialize]
public void TestInitialize()
{
    _data = new List<StubEntity>
    {
        new StubEntity {Id = 1, Name = "Entity 1"},
        ...
    };
    var queryableData = _data.AsQueryable();

    var mockDbSet = new Mock<DbSet<StubEntity>>();
    mockDbSet
        .Setup(m => m.Where(It.IsAny<Expression<Func<StubEntity, bool>>>()))
        .Returns<Expression<Func<StubEntity, bool>>>(p => queryableData.Where(p));

    var context = new Mock<StubContext>();
    context.Setup(x => x.DbEntities).Returns(mockDbSet.Object);
    context.Setup(x => x.Set<StubEntity>()).Returns(mockDbSet.Object);

    _repository = new Repository<StubEntity>(context.Object);
}

我只是在测试中将where子句作为测试条件

[TestMethod]
public void Find_ReturnsProperEntity()
{
    var entity = _repository.Find(s => s.Id == 1);
    ....
}

在此情况下,Find方法只会调用上下文的where子句。

public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
    return Context.Set<TEntity>().Where(predicate);
}

你看过这个答案吗?https://dev59.com/aV8e5IYBdhLWcg3wNYUn - cecilphillip
1个回答

2

Moq在处理非虚拟成员(方法/属性)时会出现问题,并且在遇到这些成员时会抛出异常。

例如:

System.NotSupportedException: System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: x => x.DbEntities.

这里的假设是您的StubContext看起来像这样...

public class StubContext : DbContext {
    //...code removed for brevity

    public DbSet<StubEntity> DbEntities { get; set; }

    //...other code removed for brevity
}

...当需要编辑时,应使用虚拟属性进行编辑,例如...

public class StubContext : DbContext {
    //...code removed for brevity

    public virtual DbSet<StubEntity> DbEntities { get; set; }

    //...other code removed for brevity
}

使用以下实用类

using Moq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

public static class MockDbSet {
    public static Mock<DbSet<T>> Create<T>(params T[] elements) where T : class {
        return elements.AsDbSetMock();
    }
}

public static class MockDbSetExtensions {
    public static Mock<DbSet<T>> AsDbSetMock<T>(this IEnumerable<T> list) where T : class {
        IQueryable<T> queryableList = list.AsQueryable();
        Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
        dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
        dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
        return dbSetMock;
    }
}

我使用模拟的 DbSet 重新创建了您的单元测试,并使用建议的修复方案...

[TestClass]
public class MockDbSetTests {
    private List<StubEntity> _data;
    private Repository<StubEntity> _repository;

    [TestInitialize]
    public void TestInitialize() {
        _data = new List<StubEntity>
        {
            new StubEntity {Id = 1, Name = "Entity 1"},
            //...
        };

        var mockDbSet = _data.AsDbSetMock();

        var context = new Mock<StubContext>();
        context.Setup(x => x.DbEntities).Returns(mockDbSet.Object);
        context.Setup(x => x.Set<StubEntity>()).Returns(mockDbSet.Object);

        _repository = new Repository<StubEntity>(context.Object);
    }

    [TestMethod]
    public void Find_Should_Return_Proper_Entity() {
        //Act
        var entity = _repository.Find(s => s.Id == 1);
        //Assert
        Assert.IsNotNull(entity);
        Assert.IsTrue(entity.Count() == 1);
    }
}

...并且测试通过(绿色)。


我尝试使用 EntityFrameworkCore,但如果我的测试包括调用 Where(),那么对该调用结果调用 Count 时会抛出 NullReferenceException 异常: Result StackTrace: at lambda_method(Closure , Value ) at System.Linq.Enumerable.WhereListIterator1.GetCount(Boolean onlyIfCheap) at System.Linq.Enumerable.Count[TSource](IEnumerable1 source) at System.Linq.Queryable.Count[TSource](IQueryable1 source)` 有任何更新 Core 的想法吗? - Buddha Buddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接