我可以在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());
但是会产生警告:尝试明确指定类型参数。
我目前不得不使用不理想的Ignored属性。
答案 0 :(得分:2)
“匹配” - 方法需要一个lambda,但你试图将表达式传递给它。你想用“匹配”来表达什么?你在平等上匹配吗?在那种情况下,你只需写:
A.CallTo(()=&gt; repository.Single(myExpression))。返回(new Flight());
如果要将表达式约束在其他内容上,则必须将类型谓词Func<Expression<Func<Flight, bool>>, bool>
传递给“匹配”方法。
答案 1 :(得分:2)
感谢Patrik,
检查表达式正是我需要做的,即解析表达式( f =&gt; 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());
然而,我不禁想到必须有一种更优雅的方式来达到同样的目的。我会把它留给另一天。
再次感谢, Michael McDowell
答案 2 :(得分:0)
我在尝试将表达式断言为参数时遇到了同样的问题,但我使用的是Moq。解决方案应该对你有用......
我对这个类似问题的答案给予了大部分赞誉: Moq Expect On IRepository Passing Expression
它基本上说你可以对表达式做一个ToString()并比较它们。它有点像hacky但它只有一个缺点; 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表达式的变量名,它在测试中会是相同的。