【问题标题】:Moq with lambda expressions?带 lambda 表达式的起订量?
【发布时间】:2011-09-12 05:53:57
【问题描述】:

我正在尝试使用 Moq 4.0.10827(在 NuGet 上)测试应用程序服务,并且需要查询存储库:

public class MyService
{
    Repository<MyObject> _Repo;

    public MyObject Get (string SomeConstraint)
    {
        return _Repo
            .GetTheFirstOneOrReturnNull (M => M.Constraint.Equals (
                SomeContraint, StringComparison.InvariantCultureIgnoreCase
            ));  // GetTheFirstOneOrReturnNull takes a Func<MyObject, bool>
    }
}

如何使用 Moq 复制 lambda 表达式?我不断收到“不支持的表达式”异常。

这是我已经在做的事情的一个想法:

[TestMethod]
public void GetByMyConstraintShouldReturnWithMyObject ()
{
    // Arrange
    const string MyConstraint = "Constraint";
    MyObject Expected = new MyObject { Constraint = MyConstraint };
    Mock<Repository<MyObject>> MockRepo = new Mock<Repository<MyObject>> ();
    MockRepo.Setup (x => x.GetTheFirstOneOrReturnNull (M => M.Constraint.Equals (MyConstraint, StringComparison.InvariantCultureIgnoreCase)))
            .Returns (Expected).Verifable ();
    MyService Service = new MyService (MockRepo.Object);

    // Act
    MyObject Result = Service.Get (MyConstraint);


    // Assert
    Assert.AreSame (Expected, Result);
    MockRepo.Verify ();

}

我查看了其他一些答案,但我无法真正弄清楚我做错了什么(诚然,Moq 是“菜鸟”)。我得出的结论是这会很痛苦,但我有很多这样的测试即将到来,我想现在变得稳固而不是以后淹死。

将 lambda 表达式封装在对象中并传入存储库并让它执行查询的唯一选项是什么?我不想仅仅为了我的测试环境而改变我的代码,但我也不想浪费时间试图让这件事屈服于我的意愿。

【问题讨论】:

    标签: c# visual-studio unit-testing lambda moq


    【解决方案1】:

    这应该不需要太多测试。一项正确的测试将显示委派给FirstOrDefault 的代码正在运行,然后所有后续测试都在真正测试Func 约束中的逻辑是否正确,无需将其传递给Repository 即可完成。

    【讨论】:

    • 嗯...也许我的问题并没有描述我真正想要测试的内容。我可以不关心回购,这就是我嘲笑它的原因。我只想对服务进行测试。我带着一个自定义存根而不是这个最小起订量。它似乎不能很好地处理 Func
    【解决方案2】:

    您似乎在尝试模拟扩展方法。您不能以这种方式模拟扩展方法,因为它们实际上并未在您要模拟的类型上声明。

    在这种情况下,由于您的存储库似乎代表了事物的集合,因此您应该替换为简单的硬编码集合。由于您没有提供IRepository 的源代码,因此尚不清楚您将如何处理。

    【讨论】:

    • 我不确定添加存储库对这里有什么帮助。它只是返回第一个或默认值,在这种情况下,无论它的后备存储是什么(内存或数据库,无关紧要)。 FirstOrDefault 只是我在示例中给出的方法名称——它实际上是由存储库类定义的,并采用 Func.
    【解决方案3】:

    我想说你最好的办法是更新你的Repository 以拥有类似FindByConstraint 的方法,你传入的只是Constraint,而回购本身就是FirstOrDefault()。我认为这样做有合理的设计理由,并且只是为了更容易测试 - 搜索是不区分大小写的,并且会愉快地返回 null,您可以将其视为 Repo 应该做出的决定,而不是它的客户.

    我个人认为难以测试对象意味着我的设计存在缺陷,我认为易于测试的对象是值得努力的。

    【讨论】:

    • 我完全同意你的最后陈述。我计划重构并使存储库更友好,这只是我在测试需要 Func 的东西时遇到的问题,我想知道 Moq 是否可以很好地使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-02
    • 2021-10-25
    • 1970-01-01
    • 2016-09-22
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多