您将如何对ExpressionVisitor进行单元测试?

时间:2012-09-10 21:34:26

标签: c# iqueryable expressionvisitor

我在企业环境中工作,我们的前端(客户端和Web)没有直接的数据库访问权限,而是通过网络与服务进行通信。外部可用的ASP.Net Web API的概念验证工作已经开始,我们正在考虑尝试使用IQueryable的实现来使用OData。问题是,Web API将是访问网络跳跃的服务层的另一个“前端”,这意味着我们必须编写自己的IQueryable实现。

一个IQueryable实现就是我所说的RangeQueryable,它是抽象的并且带有三个通用参数; TRaw,TData,TRange。这将是IQueryable<TData>

var queryable = new RangeQueryableImplementation<RawData, ConvertedData, DateTime>("Created");

在前面的代码行中RawData是TRaw,ConvertedData是TData,DateTime是TRange。

RangeQueryable也有两个抽象方法。

public abstract IEnumerable<TRaw> GetData(TRange from, TRange to);
public abstract TData Convert(TRaw raw);

GetData将通过网络调用服务层,并使用fromto作为调用中的参数。转换然后将数据转换为我的类型。

TRaw是服务将返回的类型,TData是前端中的类型,IQueryable中的类型,而TRange是范围类型。

所以这是可能的:

queryable.Where(d => d.Created < DateTime.Now && d.Created > DateTime.Now.AddDays(-5))

......或OData等价物。

这就是ExpressionVisitor的用武之地。我需要使用ExpressionVisitor来查找From和To日期。

我查看了一些教程并提出了一些想法。我遇到的问题是我不知道如何对ExpressionVisitor进行单元测试。我如何创建一个与Queryable扩展方法创建的表达式相同的表达式?

1 个答案:

答案 0 :(得分:1)

我会将每个测试用例写成具有某个表达式树作为输入,并且(在您的情况下)期望某个范围作为输出。可以通过多种方式指定表达式树: - 您可以通过调用Expression.Call等手动创建表达式树(每种类型的表达式节点在Expression类型上都有一个静态方法来创建它)。 - 您可以使用上面的扩展方法创建表达式树 - 您可以使用查询理解来创建表达式树(从语法中选择)

每个都将以表达式树结束。扩展方法最终调用Expression。方法也是如此。其中大多数实际上只是将一个Call表达式注入到树中 - 您可以查看反汇编程序或调试器中公开可用的源代码。

查询理解语法只是将调用写入扩展方法的另一种方式,所以你最终也会得到同样的东西。

在单元测试中,您甚至不必运行可查询,因此只需创建它,将表达式树应用于它,并运行表达式访问者就足够了。