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设置为返回两个对象的列表,而不管传递的函数是什么。那么我如何才能让测试尊重这个函数呢?
我认为问题出在这里
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));