Moq与lambda表达式?

问题描述 投票:3回答:3

我正在尝试使用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的“noob”)。我得出结论,这将是一个痛苦,但我有很多这样的测试即将到来,并希望现在变得坚实,而不是以后溺水。

是将lambda表达式封装在对象内部并传入存储库并让它执行查询的唯一选项吗?我不想仅仅为了我的测试环境而改变我的代码,但我也不想浪费时间试图将这个东西弯曲到我的意愿。

c# visual-studio unit-testing lambda moq
3个回答
1
投票

这不需要太多测试。一个正确的测试将显示委托给FirstOrDefault的代码正在工作,然后所有后续测试都在测试Func约束中的逻辑是否正确,这可以在不将其传递到Repository的情况下完成。


1
投票

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

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


1
投票

我要说你最好的选择是更新你的Repository有类似FindByConstraint方法的东西,你传入的所有内容都是Constraint,Repo本身就是FirstOrDefault()。我认为这样做有合理的设计理由,而且只是为了让它更容易测试 - 搜索正在以不区分大小写的方式执行,并且很乐意返回null,您可以将其视为Repo应该制作的决策而不是其客户端。

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

© www.soinside.com 2019 - 2024. All rights reserved.