2013-04-03 48 views
4

我以前有一个看起来像这样的一个Web API控制器:

public IQueryable<ApiDesignOverview> GetList(
     string brandIds = "", 
     string categoryIds = "", 
     string query = "", 
     string categoryOp = "or") 

听说OData的NuGet包现在支持$ inlinecount OData的参数,所以我试图请使用http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options中的说明添加它 - 我不想使用OData批发,因为这需要大量重新构建应用程序,所以我选择了PageResult<T>选项。

所以现在我的控制器看起来是这样的:

public PageResult<ApiDesignOverview> GetList(
     ODataQueryOptions<ApiDesignOverview> options, 
     string brandIds = "", 
     string categoryIds = "", 
     string query = "", 
     string categoryOp = "or") 

我的问题现在就是:

  • 我怎么嘲笑一个单元测试ODataQueryOptions?
  • 如果他们不能被嘲笑,我该如何创建一个?我需要一个ODataQueryContext来构建一个,这需要Microsoft.Data.Edm.IEdmModel,这需要......什么?我找不到任何文件。

真的,如果我可以像从前一样从控制器签名中删除ODataQueryOptions会更好。这可能吗?

回答

8

如果您希望返回IQueryable,但希望获得对$ inlinecount的支持,则仍可以通过对QueryableAttribute进行定制来实现。

public class InlineCountQueryableAttribute : QueryableAttribute 
{ 
    private static MethodInfo _createPageResult = 
     typeof(InlineCountQueryableAttribute) 
     .GetMethods(BindingFlags.Static | BindingFlags.NonPublic) 
     .Single(m => m.Name == "CreatePageResult"); 

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
    { 
     base.OnActionExecuted(actionExecutedContext); 

     HttpRequestMessage request = actionExecutedContext.Request; 
     HttpResponseMessage response = actionExecutedContext.Response; 

     IQueryable result; 
     if (response.IsSuccessStatusCode 
      && response.TryGetContentValue<IQueryable>(out result)) 
     { 
      long? inlineCount = request.GetInlineCount(); 
      if (inlineCount != null) 
      { 
       actionExecutedContext.Response = _createPageResult.MakeGenericMethod(result.ElementType).Invoke(
        null, new object[] { request, request.GetInlineCount(), request.GetNextPageLink(), result }) as HttpResponseMessage; 
      } 
     } 
    } 

    internal static HttpResponseMessage CreatePageResult<T>(HttpRequestMessage request, long? count, Uri nextpageLink, IEnumerable<T> results) 
    { 
     return request.CreateResponse(HttpStatusCode.OK, new PageResult<T>(results, nextpageLink, count)); 
    } 
} 

请注意,我使用反射来创建PageResult。你可以返回一个你喜欢的对象,它可以被你使用的格式化器格式化。如果您使用的是Json格式器,则具有结果和计数的匿名对象也可以工作。

11

如果不这样做(或无法在我的情况)要使用ODataQueryOptions和PageResult客场改变,这里是你如何为单元测试创​​建ODataQueryOptions实例:

//arrange 
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/MyProject/api/Customers?$filter=CustomerID eq 1"); 
var controller = new CustomersController 
{ 
    Request = request 
}; 

ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
modelBuilder.EntitySet<Customer>("Customers"); 
var opts = new ODataQueryOptions<Customer>(new ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)), request); 

//act 
var result = controller.Get(opts); 

//assert 
Assert.AreEqual(1, result.Items.First().CustomerID); 
+0

有没有办法做到这一点EntitySets与许多相关的实体,其中没有任何与您的测试逻辑相关?请参阅:http://stackoverflow.com/questions/17477421/instantiate-new-system-web-http-odata-query-odataqueryoptions-in-nunit-test-of-a/17477481#17477481 – user483679

+0

为了进行单元测试,我需要通过顶部和跳过。我会如何做到这一点?这些字段是只读的。 – Narayana

0

在最新ODataController有一个解决这个问题的AllowedQueryOptions

public class MyOdataController : ODataController 

    { 
     [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)] 
     public IQueryable<Product> Get() 
     { 
      return Products.AsQueryable(); 
     } 
    }