带表达式的最小函数调用
本文关键字:函数调用 表达式 | 更新日期: 2023-09-27 18:09:59
我有以下接口,用于DI和IOC web服务客户端
public interface IWcfServiceClientProvider <TContract>: IDisposable where TContract: class
{
TResult Execute<TResult>(Expression<Func<TContract, TResult>> expression);
TResult Execute<TResult>(Expression<Func<TContract, TResult>> expression, bool closeConnection = true);
void Execute(Expression<Action<TContract>> expression);
void Execute(Expression<Action<TContract>> expression, bool closeConnection = true);
}
在我的测试类中,我有以下内容:
List<BaseLookup> myList = new List<BaseLookup> {
new BaseLookup { Id =1, Code = "1001"},
new BaseLookup { Id =2, Code = "1002"},
new BaseLookup { Id =3, Code = "1003"}};
在我的测试方法
Mock<IWcfServiceClientProvider<ILookupService>> lookupServiceClinetProvider = new Mock<IWcfServiceClientProvider<ILookupService>>();
var controller = new ElectorSearchController(lookupServiceClinetProvider.Object);
lookupServiceClinetProvider.Setup(mock => mock.Execute(lookup => lookup.GetList(10))).Returns(myList).Verifiable();
var list = controller.testMethod();
lookupServiceClinetProvider.VerifyAll();
list只有当GetList
的参数设置为10时才有值,即GetList(10)
,而不是GetList(i)
,其中i=10
以下作品
lookupServiceClinetProvider.Setup(mock => mock.Execute(It.IsAny<Expression<Func<ILookupService, List<BaseLookup>>>>(), true )).Returns((List<BaseLookup>)myList).Verifiable();
但是我想模拟GetList
的调用,而不是任何调用Execute。如果有效,那么我可以过滤Return
方法中的值
作为临时解决方案,我编写了一个简单的蛮力解决方案来比较以下表达式:
public static bool ExpressionMatcher<TIn, TResult>(Expression<Func<TIn, TResult>> expr1, Expression<Func<TIn, TResult>> expr2)
{
if (expr1 == null || expr2 == null)
{
return false;
}
if (expr1 == expr2)
{
return true;
}
if (expr1.Type != expr2.Type)
{
return false;
}
if (expr1.Body == expr2.Body)
{
return true;
}
if (expr1.Body.NodeType != expr2.Body.NodeType)
{
return false;
}
if (expr1.Body.NodeType == ExpressionType.Call)
{
dynamic expr1Body = expr1.Body;
dynamic expr2Body = expr2.Body;
if (expr1Body.Method.Name == expr2Body.Method.Name &&
expr1Body.Method.ReturnType == expr2Body.Method.ReturnType)
{
if (expr1Body.Arguments == null && expr2Body.Arguments == null)
{
return true;
}
if (expr1Body.Arguments.Count != expr2Body.Arguments.Count)
{
return false;
}
return true;
}
}
return false;
}
我用下面的代码将它命名为
Expression<Func<ILookupService, List<BaseLookup>>> expr = lookup => lookup.GetMyList(It.IsAny<long>());
.Setup(mock => mock.Execute(It.Is<Expression<Func<ILookupService, List<BaseLookup>>>>(method => ExpressionMatcher(method, expr))))
.Returns(myList)
.Verifiable();
此时我不需要检查参数的类型。如果你有更好的答案,请告诉我