在 ASP.NET Web API 控制器的 nunit 测试中实例化新的 System.Web.Http.OData.Query.ODataQueryOptions

Posted

技术标签:

【中文标题】在 ASP.NET Web API 控制器的 nunit 测试中实例化新的 System.Web.Http.OData.Query.ODataQueryOptions【英文标题】:Instantiate new System.Web.Http.OData.Query.ODataQueryOptions in nunit test of ASP.NET Web API controller 【发布时间】:2013-07-02 21:07:35 【问题描述】:

我有一个带有 ApiController 继承控制器的 ASP.NET MVC4 Web API 项目,该控制器接受 ODataQueryOptions 参数作为其输入之一。

我正在使用 NUnit 和 Moq 来测试项目,这允许我从 ApiController 使用的相关存储库方法设置预设响应。这有效,如下所示:

[TestFixture]
public class ProjectControllerTests

    [Test]
    public async Task GetById()
    
        var repo = new Mock<IManagementQuery>();

        repo.Setup(a => a.GetProjectById(2)).Returns(Task.FromResult<Project>(new Project()
         
              ProjectID = 2, ProjectName = "Test project", ProjectClient = 3
        ));

        var controller = new ProjectController(repo.Object);
        var response = await controller.Get(2);

        Assert.AreEqual(response.id, 2);
        Assert.AreEqual(response.name, "Test project");
        Assert.AreEqual(response.clientId, 3);
    

我面临的挑战是,要使用这种模式,我需要将相关的查询字符串参数传递给控制器​​以及存储库(这实际上是我的意图)。但是,在接受 ODataQueryOptions 的 ApiController 方法的情况下,即使在我只想使用 ODataQueryOptions 的默认参数的情况下,我也需要知道如何实例化一个。这变得很棘手:

ODataQueryOptions 没有实现接口,所以无法直接模拟。 构造函数需要一个 System.Web.Http.OData.ODataQueryContext 的实现,这需要一个实现 Microsoft.Data.Edm.IEdmModel 的东西的实现,文档很少,Visual Studio 2012 Find References and View Call Hierarchy不提供见解(什么实现了该接口?)。

我需要做什么/有更好的方法吗?

谢谢。

【问题讨论】:

【参考方案1】:

看起来其他人已经在 cmets here 中回答了这个问题,但这不是我的用例的完整解决方案(见下面的评论):

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

【讨论】:

好吧,由于我的 EntitySet 是从 EntityFramework 模型派生的,而且它们在很大程度上是相关的对象,看来我需要为我的 objectcontext 中的每个 TEntity 提供一个 EntitySet ......这是真的吗?必须有一种方法可以从 objectcontext => odataqueryoptions 出发,对吧?【参考方案2】:

这是我在 NUnit 测试中用于注入 ODataQueryOptions 的解决方案

private static IEdmModel _model;
private static IEdmModel Model

    get
    
        if (_model == null)
        
            var builder = new ODataConventionModelBuilder();

            var baseType = typeof(MyDbContext);
            var sets = baseType.GetProperties().Where(c => c.PropertyType.IsGenericType && c.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>));
            var entitySetMethod = builder.GetType().GetMethod("EntitySet");
            foreach (var set in sets)
            
                var genericMethod = entitySetMethod.MakeGenericMethod(set.PropertyType.GetGenericArguments());
                genericMethod.Invoke(builder, new object[]  set.Name );
            

            _model = builder.GetEdmModel();
        

        return _model;
    


public static ODataQueryOptions<T> QueryOptions<T>(string query = null)

    query = query ?? "";
    var url = "http://localhost/Test?" + query;
    var request = new HttpRequestMessage(HttpMethod.Get, url);
    return new ODataQueryOptions<T>(new ODataQueryContext(Model, typeof(T)), request);

【讨论】:

以上是关于在 ASP.NET Web API 控制器的 nunit 测试中实例化新的 System.Web.Http.OData.Query.ODataQueryOptions的主要内容,如果未能解决你的问题,请参考以下文章

所有 ASP.NET Web API 控制器都返回 404

ASP.NET MVC 4 Web API

ASP.NET Web API 从 MVC 4 控制器失败

如何在 ASP.NET Web API 中指定控制器的名称?

为啥 Asp.net web api 控制器不从 IController 派生

《ASP.NET5》无法路由到Web API Controller控制器