【问题标题】:Web API, OData, $inlinecount and testingWeb API、OData、$inlinecount 和测试
【发布时间】:2013-03-25 07:35:52
【问题描述】:

我之前有一个如下所示的 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&lt;T&gt; 选项。

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

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

我现在的问题是:

  • 如何模拟 ODataQueryOptions 以进行单元测试?
  • 如果它们不能被模拟,我如何创建一个?我需要一个ODataQueryContext 来构造一个,这需要一个Microsoft.Data.Edm.IEdmModel,这需要......什么?我找不到这方面的任何文档。

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

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api odata


    【解决方案1】:

    在最新的ODataController 中有一个AllowedQueryOptions 可以解决这个问题。

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

    【讨论】:

      【解决方案2】:

      如果您不想(或不能像我一样)不想改变使用 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);
      

      【讨论】:

      • 有没有办法为具有许多相关实体的实体集执行此操作,但这些实体都与您的测试逻辑无关?见:stackoverflow.com/questions/17477421/…
      • 为了进行单元测试,我需要传入Top和Skip。我该怎么做呢?这些字段是只读的。
      【解决方案3】:

      如果您更喜欢返回 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 格式化程序,带有结果和计数的匿名对象也可以工作。

      【讨论】:

        猜你喜欢
        • 2013-03-03
        • 2013-08-28
        • 2012-05-29
        • 2012-07-03
        • 2013-03-11
        • 1970-01-01
        • 2015-02-06
        • 2011-10-08
        • 2015-09-04
        相关资源
        最近更新 更多