12

我有一个带有 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 没有实现接口,所以不能直接mock。
  • 构造函数需要一个 System.Web.Http.OData.ODataQueryContext 的实现,这需要一个实现 Microsoft.Data.Edm.IEdmModel 的东西的实现,文档很少,Visual Studio 2012 Find References 和 View Call Hierarchy 不提供洞察力(什么实现了该接口?)。

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

谢谢。

4

2 回答 2

7

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

ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
modelBuilder.EntitySet<Customer>("Customers"); 
var opts = new ODataQueryOptions<Customer>(new ODataQueryContext(modelBuilder.GetEdmModel(),typeof(Customer)), request);
于 2013-07-04T20:04:37.950 回答
3

这是我在 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);
}
于 2015-01-10T00:28:39.167 回答