【问题标题】:Using Moq for a repository interface method?将 Moq 用于存储库接口方法?
【发布时间】:2013-03-01 22:35:05
【问题描述】:

我的仓库界面有以下方法:

IQueryable<T> GetQuery<T>(Expression<Func<T, bool>> predicate) where T : class;

我有一个要在单元测试中使用以下构造函数的类:

public MyClass(IUnitOfWork unitOfWork)

IUnitOfWork 接口上有一个暴露的存储库属性:

Repository Repository { get; }

所以我尝试像这样对MyClass.DoSomething() 方法进行单元测试:

[TestInitialize]
public void Setup()
{

    accounts = new List<Account>()
    {
        new Account()
            {
               Id = 123
            }
    };
}

接下来我的单元测试Arrange 部分失败了:

//Arrange
var repositoryMock = new Mock<IUnitOfWork>();
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(y => y.Id == 123))
                           .Returns(accounts.AsQueryable()); //This setup always fails
var myClass = new MyClass(repositoryMock.Object); //don't even get here

我得到的例外是:

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

我在模拟中尝试了Setup 的其他变体:

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

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

但没有成功;我每次都得到相同的异常。当我运行单元测试时,它们总是抛出相同的异常。由于我使用的是要模拟的接口,为什么会出现此异常以及如何正确执行此操作?谢谢!

【问题讨论】:

    标签: c# moq


    【解决方案1】:

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

    //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); 
    

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

    【讨论】:

    • 这正是我所需要的,但是当我调用使用注入的 mockd 存储库的myClass.DoSomething 时,内部调用的查询不会产生任何结果。没有错误,只是没有返回任何内容。我已经查看了 20 倍以上的代码,这一切似乎都说得通:“这是存储库的一个模拟实例,它将在调用 Repository.GetQuery&lt;Account&gt; 时返回列表 accounts。”那么为什么一个简单的查询不会产生任何结果呢? (关于不需要传递具体 lambda 的好点 - 是的,我总是希望返回整个列表)。
    • 没关系 - 想通了。我在存储库中有 2GetQuery 的实现。一个接受一个表达式,另一个只是一个实体。我正在测试的重载实际上是刚刚获取实体的重载。我正在对返回的IQuerable 结果编写查询,以 then 应用附加的 lambda 表达式过滤。因此,如果我的查询一直提供表达式作为对 GetQuery 的原始调用的一部分,那么您的代码将起作用。在我的 OP 时,我并不了解所有这些。感谢您的帮助。
    【解决方案2】:

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

    IRepository Repository { get; }
    

    【讨论】:

    • 技术上是我原来的帖子的答案,以解决我遇到的错误。然而,即使应用了这个,我的原始查询和语法仍然不正确,@HuseinRoncevic 的回答解决了我无论如何都会遇到的另一个问题。感谢两者,将此标记为答案。
    猜你喜欢
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多