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 进行单元测试?
  • 如果他们不能被嘲笑,我该如何创造一个?我需要 aODataQueryContext来构建一个,这需要 a Microsoft.Data.Edm.IEdmModel,这需要...什么?我找不到任何文档。

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

4

3 回答 3

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);
于 2013-05-03T14:56:19.467 回答
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 格式化程序,带有结果和计数的匿名对象也可以工作。

于 2013-04-03T16:10:06.660 回答
0

最近ODataController有一个AllowedQueryOptions可以解决这个问题。

public class MyOdataController : ODataController

    {
        [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
        public IQueryable<Product> Get()
        {
            return Products.AsQueryable();
        }
    }
于 2014-01-18T00:38:49.123 回答