使用表达式树作为参数约束
本文关键字:参数约束 表达式 | 更新日期: 2023-09-27 18:09:42
我可以在FakeIteasy CallTo断言中使用表达式树作为参数约束吗?
给定接口上具有以下签名的方法:
interface IRepository<TEntity>
{
TEntity Single(Expression<Func<TEntity, bool>> predicate);
在代码中被这样调用:
Flight flight = repository.Single(f => f.ID == id);
我想到了这样一个单元测试:
Expression<Func<Flight, bool>> myExpression = flight => flight.ID == 1;
A.CallTo(() => repository.Single(
A<Expression<Func<Flight, bool>>>.That.Matches(myExpression)))
.Returns(new Flight());
但是这会产生一个警告:尝试显式指定类型参数。
我目前不得不使用忽略属性,这是不理想的。
"Matches"-方法接受lambda,但您试图将表达式传递给它。你叫我"配对"是想说什么?你们是平等配对吗?在这种情况下,你只需写:
callto (() => repository.Single(myExpression))。返回(新飞行());如果你想把表达式约束在其他东西上,你必须传递一个类型为:Func<Expression<Func<Flight, bool>>, bool>
的谓词到"Matches"方法。
谢谢patrick,
检查表达式正是我需要做的,即解析表达式(f => f.ID == id)并执行==的右侧以获得其运行时值。
在代码中是这样的:
A.CallTo(() => flightRepository.Single(A<Expression<Func<Flight, bool>>>.That
.Matches(exp => Expression.Lambda<Func<int>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == 1)))
.Returns(new Flight());
然而,我忍不住想一定有一种更优雅的方式来达到同样的目的。不过我还是改天再说吧。
再次感谢,迈克尔·麦克道尔
我有同样的问题,而试图断言表达式作为一个参数,但我正在使用Moq。解决方案应该也适用于你…
我把大部分功劳归功于对一个类似问题的回答:Moq Expect On IRepository Passing Expression
它基本上说你可以对表达式执行ToString()并比较它们。这有点俗气,但它只有一个缺点; lambda表达式中的变量名必须匹配
[Test]
public void TestWhichComparesExpressions()
{
// setup
_mockRepository.Setup(x => x.GetByFilter(MatchQuery())).Returns(new List<Record>());
// execute
var records = _service.GetRecordsByFilter();
// assert
Assert.IsNotNull(records);
Assert.AreEqual(0, records.Count());
}
private static Expression<Func<DomainRecord, bool>> MatchQuery()
{
return MatchExpression(ServiceClass.QueryForTheRecords); // constant
}
// https://stackoverflow.com/questions/288413/moq-expect-on-irepository-passing-expression/1120836#1120836
private static Expression<Func<DomainRecord, bool>> MatchExpression(Expression<Func<DomainRecord, bool>> expression)
{
return It.Is<Expression<Func<DomainRecord, bool>>>(e => e.ToString() == expression.ToString());
}
我决定将表达式放入使用它的类的常量中,以保证如果有人更改了lambda表达式的变量名,则在测试中它将是相同的。