简体   繁体   English

为什么用Expression模拟 <Func<T,bool> 不匹配?

[英]Why this mock with Expression<Func<T,bool> is not matching?

i am new on mock and i am trying to do this mock example : 我是模拟的新手,我正在尝试做这个模拟示例:

Repository.cs 仓库.cs

public class Repository : IRepository
{
    public List<Person> GetForExpression(Expression<Func<Person,bool>> expression  )
    {
        ... //get person from orm using expression
    }
}

PersonService.cs PersonService.cs

public class PersonService
{
    private IRepository _repository;
    public PersonService(IRepository repository)
    {
        _repository = repository;
    }

    public List<Person> GetAllPersonsWith18More()
    {            
        var result = _repository.GetForExpression(x => x.Age > 18);

        return result;

    }
}

Test: 测试:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var moqRepository = new Mock<IRepository>();
        var service = new PersonService(moqRepository.Object);
        Expression<Func<Person, bool>> criteria = y => y.Age  18;
        moqRepository.Setup(x => x.GetForExpression(It.Is<Expression<Func<Person, bool>>>(y => y == criteria))).Returns(new List<Person>());
        service.GetAllPersonsWith18More();
        moqRepository.VerifyAll();
    }
}

if i use this setup works: moqRepository.Setup(x => x.GetForExpression(It.IsAny>>())).Returns(new List()); 如果我使用此安装程序有效:moqRepository.Setup(x => x.GetForExpression(It.IsAny >>()))。Returns(new List());

but i want to use more specific criteria, this is only one example that i do to demonstrate what i need. 但是我想使用更具体的标准,这只是我演示我所需要的一个示例。

This example is not matching, can anyone help to understand why and solve this problem? 此示例不匹配,任何人都可以帮助理解原因并解决此问题吗?

Expressions are not comparable, so == will return false even if expression trees exactly matches: 表达式不可比,因此即使表达式树完全匹配,==也会返回false:

int criteria = 5;
Expression<Func<int, bool>> criteria1 = y => y == criteria;
Expression<Func<int, bool>> criteria2 = y => y == criteria;
System.Diagnostics.Debug.WriteLine(criteria1 == criteria2); // false

As workaround, you can call expression.ToString() and compare string representations: Comparing Simple Lambda Expressions With Moq . 解决方法是,您可以调用expression.ToString()并比较字符串表示形式: 比较简单的Lambda表达式和Moq

Expressions can't be compared like that. 表达式无法像那样进行比较。 If you want to match expressions in that much detail, you need to take the expression passed to your mock and parse it's tree (as outlined in this answer ). 如果要详细地匹配表达式,则需要将传递给模拟的表达式解析为树(如本答案所述 )。 The result would look something like this (where FuncTest.FuncEqual can be found in the previous answer): 结果看起来像这样(在上一个答案中可以找到FuncTest.FuncEqual ):

moqRepository
    .Setup(x => x.GetForExpression(ExpressionMatches(criteria))
    .Returns(new List<Person>());

// ...

public static Expression<Func<TSource, TValue>> ExpressionMatches(Expression<Func<TSource, TValue>> expr)
{
    return Match.Create<Expression<Func<TSource, TValue>>(actualExpr => FuncTest.FuncEqual(expr, actualExpr));
}

If it is needed to test delegates I usually apply them to any test object. 如果需要测试代表,我通常将它们应用于任何测试对象。 In order to test PersonService I'd rather use the following code that contains examples of two tests. 为了测试PersonService,我宁愿使用下面的代码,其中包含两个测试的示例。

[TestClass]
public class UnitTest2
{
    private Mock<IRepository> moqRepository;
    private PersonService service;

    [TestInitialize]
    public void TestInitialize()
    {
        moqRepository = new Mock<IRepository>();
        service = new PersonService(moqRepository.Object);
    }

    [TestMethod]
    public void TestMethod3()
    {
        // arrange
        var persons = new List<Person>
        {
            new Person { Age = 0 },
            new Person { Age = 1 },
            new Person { Age = 17 },
            new Person { Age = 18 },
            new Person { Age = 19 },
            new Person { Age = 100 }
        };
        moqRepository
            .Setup(x => x.GetForExpression(It.IsAny<Expression<Func<Person, bool>>>()))
            .Returns<Expression<Func<Person, bool>>>(expr => persons.Where(expr.Compile()).ToList());

        // act
        var result = service.GetAllPersonsWith18More();

        // assert
        moqRepository.VerifyAll();
        result.Should().BeEquivalentTo(persons.Where(x => x.Age > 18));
    }

    [TestMethod]
    public void TestMethod4()
    {
        // arrange
        Expression<Func<Person, bool>> criteria = x => x.Age > 18;
        moqRepository
            .Setup(x => x.GetForExpression(It.IsAny<Expression<Func<Person, bool>>>()))
            .Returns(new List<Person>())
            .Callback<Expression<Func<Person, bool>>>(expr =>
            {
                var persons = new List<Person>
                {
                    new Person { Age = 0 },
                    new Person { Age = 1 },
                    new Person { Age = 17 },
                    new Person { Age = 18 },
                    new Person { Age = 19 },
                    new Person { Age = 100 }
                };
                persons.Where(expr.Compile()).Should().BeEquivalentTo(persons.Where(criteria.Compile()));
            });

        // act
        service.GetAllPersonsWith18More();

        // assert
        moqRepository.VerifyAll();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM