LINQ Contains语句在字符串列表的复杂对象上使用时表现不同

本文关键字:对象 语句 Contains 字符串 列表 复杂 LINQ | 更新日期: 2023-09-27 18:26:53

我是个白痴吗?这是一个模拟存储库:

Mock<IRepository> repMock = new Mock<IRepository>();
Quote q1 = new Quote { QuoteId = 123 };
Quote q2 = new Quote { QuoteId = 345 };
repMock.Setup(m => m.GetQuotes(It.IsAny<Expression<Func<Quote, bool>>>())).Returns((new List<Quote> { q1, q2 }).AsQueryable);

下面是一个LINQ语句,它将这些Id视为字符串,并获取包含字符串"3"(即两者)的Id:

Assert.AreEqual(2, repMock.Object.GetQuotes(q => q.QuoteId.ToString().Contains("3")).Count());

以下是仅用于获取一个字符串的相同主体,但这失败了。它返回两个字符串:

Assert.AreEqual(1, repMock.Object.GetQuotes(q => q.QuoteId.ToString().Contains("1")).Count());

然而,如果你把字符串拉到他们自己的列表中,并根据它运行contains,它会像预期的那样工作:

List<string> foo = repMock.Object.GetQuotes(q => q.QuoteId.ToString().Contains("3")).Select(q => q.QuoteId.ToString()).ToList();
Assert.AreEqual(1, foo.Where(f => f.Contains("1")).Count());

这是怎么回事?这段代码似乎真的能在生产中工作,并按预期过滤字符串——它只在单元测试中失败?

编辑:我看到了@IvanStoev在这里所说的逻辑,我将Mock设置为返回两个对象的列表,而不管传递的函数是什么。那么我如何才能让测试尊重这个函数呢?

LINQ Contains语句在字符串列表的复杂对象上使用时表现不同

我认为问题出在这里

repMock.Setup(m => m.GetQuotes(It.IsAny<Expression<Func<Quote, bool>>>()))
    .Returns((new List<Quote> { q1, q2 }).AsQueryable);

我对mockup框架不是很熟悉,但从逻辑上讲,您似乎正在设置接收谓词的GetQuotes函数,以始终返回整个列表,忽略传递的谓词,所以这就是为什么您的测试代码总是返回2项的原因。

更新:根据您的编辑,我想您可以使用类似的东西

repMock.Setup(m => m.GetQuotes(It.IsAny<Expression<Func<Quote, bool>>>()))
    .Returns((Expression<Func<Quote, bool>> predicate) => 
        (new List<Quote> { q1, q2 }).AsQueryable().Where(predicate));