我有一个查询
var myRecord = myRepository.All().Any(e => e.Id == id);
我用这个来 mock 它
this._myMockRepository
.Setup(s => s.All().Any(It.IsAny<Expression<Func<MyObject, bool>>>()))
.Returns(this.GetFakeMyObjects().Any(t => t.Id == 1));
如何模拟 .All().Any(...)
调用?我得到的异常是 NotSupportedException
消息:
Expression references a method that does not belong to the mocked object: s => s.All().Any < MyRepositoryObject > (It.IsAny < Expression`1 > ())
我试过这样分解它
this._myMockRepository
.Setup(s => s.All(It.IsAny<Expression<Func<MyObject, bool>>>()))
.Returns(this.GetFakeMyObjects());
this._myMockRepository
.Setup(s => s.All().Any(It.IsAny<Expression<Func<MyObject, bool>>>()))
.Returns(this.GetFakeMyObjects().Any(t => t.Id == 1));
对于 Moq 来说还很新,所以任何提示都将不胜感激。
最佳答案
更新
如果 All()
不是扩展方法,则更新模拟设置以在调用时返回可查询。
this._myMockRepository
.Setup(_ => _.All())
.Returns(this.GetFakeMyObjects());//<-- assuming GetFakeMyObjects returns an enumerable
这假设一个存储库定义了类似的东西
public interface IRepository {
IEnumerable<MyObject> All();
}
或接近该定义。
原始答案
这些都是扩展方法。 Moq 不模拟扩展方法。
您需要模拟的是调用模拟成员时返回的满足提供的 linq 查询的内容。
基于代码片段的假设表明模拟的主题是可枚举的。
以下扩展方法可用于模拟在可枚举模拟上执行查询所需的行为。
/// <summary>
/// Converts a generic <seealso cref="System.Collections.Generic.IEnumerable<T>"/> to a <see cref="Moq.Mock"/> implementation of queryable list
/// </summary>
public static Mock<T> SetupQueryable<T, TItem>(this Mock<T> queryableMock, IEnumerable<TItem> source)
where T : class, IEnumerable<TItem> {
var queryableList = source.AsQueryable();
queryableMock.As<IQueryable<TItem>>().Setup(x => x.Provider).Returns(queryableList.Provider);
queryableMock.As<IQueryable<TItem>>().Setup(x => x.Expression).Returns(queryableList.Expression);
queryableMock.As<IQueryable<TItem>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
queryableMock.As<IQueryable<TItem>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
return queryableMock;
}
并且可以像这样使用。
var fakeItems = GetFakeMyObjects();
var _myMockRepository = new Mock<IMyRepository>()
_myMockRepository.SetupQueryable(fakeItems);
这将允许在测试时在模拟对象上调用查询。
var myRepository = _myMockRepository.Object;
var myRecord = myRepository.All().Any(e => e.Id == id);
关于c# - 如何在 Moq 中模拟链式 Linq 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43982574/