2013-04-03 46 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(); 
     } 
    }