C# 将Moq用于存储库接口方法?

C# 将Moq用于存储库接口方法?,c#,moq,C#,Moq,我的存储库界面上有以下方法: IQueryable<T> GetQuery<T>(Expression<Func<T, bool>> predicate) where T : class; 在IUnitOfWork界面上有一个公开的存储库属性: Repository Repository { get; } 因此,我尝试对MyClass.DoSomething()方法进行单元测试,如下所示: [TestInitialize] public voi

我的存储库界面上有以下方法:

IQueryable<T> GetQuery<T>(Expression<Func<T, bool>> predicate) where T : class;
IUnitOfWork
界面上有一个公开的存储库属性:

Repository Repository { get; }
因此,我尝试对
MyClass.DoSomething()
方法进行单元测试,如下所示:

[TestInitialize]
public void Setup()
{

    accounts = new List<Account>()
    {
        new Account()
            {
               Id = 123
            }
    };
}
我得到的例外是:

System.NotSupportedException:非虚拟服务器上的设置无效 (在VB中可重写)成员:x=>x.Repository.GetQuery(y=> y、 Id==123)

我在模拟上尝试了
设置的其他变体

repositoryMock.Setup(x => x.Repository.GetQuery<Account>()).Returns((Account a) => accounts.AsQueryable().Where(z => z.Id == 123));
repositoryMock.Setup(x=>x.Repository.GetQuery())。返回((Account a=>accounts.AsQueryable()。其中(z=>z.Id==123));

repositoryMock.Setup(x=>x.Repository.GetQuery(y=>y.Id==123)).Returns((Account a=>accounts.AsQueryable()。其中(z=>z==a));

但是没有成功;我每次都得到相同的异常。当我运行单元测试时,它们总是抛出相同的异常。既然我在使用一个被模拟的接口,为什么我会得到这个异常,我该如何正确地做到这一点?谢谢

您显示的存储库属性不是接口类型。这是一门具体的课程。正如错误消息告诉您的,您不能定义对非虚拟方法的期望。因此,如果您希望能够模拟抽象,那么您应该做的是使用抽象:

IRepository Repository { get; }

请尝试以下操作,而不是当前的设置:

//Arrange
var repositoryMock = new Mock<IUnitOfWork>();
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(
        It.IsAny<Expression<Func<T, bool>>>());
    .Returns(accounts.AsQueryable()); // This should not fail any more
var myClass = new MyClass(repositoryMock.Object); 
//排列
var repositoryMock=new Mock();
repositoryMock.Setup(x=>x.Repository.GetQuery(
It.IsAny());
.Returns(accounts.AsQueryable());//这应该不会再失败了
var myClass=新的myClass(repositoryMock.Object);

实际上,您不需要传递任何具体的lambda,因为您正在以任何方式返回列表。

这正是我所需要的,但是当我调用
myClass.DoSomething
使用注入的mockd'存储库时,内部调用的查询不会产生任何结果。没有错误,只是没有返回任何内容。我已经查看了代码20x结束,这一切似乎都有意义:“这里有一个存储库的mockd'实例,它将在调用
存储库.GetQuery
时返回列表
accounts
。”那么为什么一个简单的查询不会产生任何结果呢?(很好的一点是,不需要传递具体的lambda-是的,我总是希望返回整个列表).Nevermind-解决了这个问题。我在存储库中有两个
GetQuery
实现。一个接受表达式,另一个只是实体。我测试的重载实际上是刚刚接受实体的重载。我正在对返回的
IQuerable
结果编写查询,然后应用附加的lambda表达式过滤器因此,如果我的查询是作为原始调用
GetQuery
的一部分提供表达式,那么你的代码就可以工作了。在我的操作时,我并没有理解所有这一切。感谢你的帮助。从技术上讲,这是对我原始帖子的回答,以解决我遇到的错误。然而,即使应用了这个,我的原始查询y和语法不正确,@HuseinRoncevic的答案解决了另一个我无论如何都会遇到的问题。
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(y => y.Id == 123)).Returns((Account a) => accounts.AsQueryable().Where(z => z == a));
IRepository Repository { get; }
//Arrange
var repositoryMock = new Mock<IUnitOfWork>();
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(
        It.IsAny<Expression<Func<T, bool>>>());
    .Returns(accounts.AsQueryable()); // This should not fail any more
var myClass = new MyClass(repositoryMock.Object);