繁体   English   中英

需要 ODataQueryOptions 的单元测试服务

[英]Unit testing service that requires ODataQueryOptions

在尝试进行一些测试驱动开发时,我创建了最基本的、可构建的方法:

public class NoteService : INoteService
{
    public IEnumerable<Annotation> GetNotes(ODataQueryOptions oDataQueryOptions)
    {
        return new List<Annotation>();
    }
}

在尝试对其进行单元测试时,似乎不可能创建 ODataQueryOptions 的实例:

[TestFixture]
public class NoteServiceTests
{
    [Test]
    public void GetNotes_Returns_IEnumerable_Of_Notes()
    {
        var sut = new NoteService();
        var queryOptions = new ODataQueryOptions(new ODataQueryContext(new EdmCoreModel(), new EdmCollectionType())// new new new etc??
                    Assert.That(() => sut.GetNotes(options), Is.InstanceOf<IEnumerable<Annotation>>());

    }
}

如何创建 object ODataQueryOptions 的简单实例以便将其注入单元测试?

这会起作用吗?

var request = new HttpRequestMessage(HttpMethod.Get, "");

var context = new ODataQueryContext(EdmCoreModel.Instance, typeof(int));

var options = new ODataQueryOptions(context, request);

我想做类似的事情并找到了一个可行的解决方案:

我的用例

我有一个 web 服务,它将 OData 查询参数向下传递到我们的 CosmosDB 文档客户端,该客户端将它们转换为 CosmosDB SQL 查询。

我想要一种直接在 CosmosDB 客户端上编写集成测试的方法,而无需对其他下游服务进行传出调用。

方法

  • 使用 Moq 尝试了 mocking ODataQueryParameters 但因为它是 class 而不是接口,所以 Moq 无法正确实例化我需要的所有属性
  • 尝试直接实例化一个,但在 MVC 应用程序之外,构建所需的 EdmModel 非常困难。
    • 想知道是否有办法在不构建 EdmModel 的情况下做到这一点?
  • 我终于找到了一种方法来做到这一点:这可能无法解决所有用例,但这是我为满足我的需要而找到的解决方案:
public static class ODataQueryOptionsBuilder
    {
        private static WebApplicationFactory<TEntryPoint> _app =
            new WebApplicationFactory<TEntryPoint>();
        
        public static ODataQueryOptions<T> Build<T>(
            string queryString) 
            where T : class
        {
            var httpContext = new DefaultHttpContext();
            httpContext.Request.QueryString = new QueryString(queryString);
            httpContext.RequestServices = _app.Services;
            var modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntityType<T>();
            var model = modelBuilder.GetEdmModel();
            var context = new ODataQueryContext(
                model, 
                typeof(T), 
                new Microsoft.AspNet.OData.Routing.ODataPath());
            return new ODataQueryOptions<T>(context, httpContext.Request);
        }
    }

结论

我意识到获得 ODataQueryOptions 所需的只是一个测试服务器,该服务器的设置与我的 web 服务完全一样。 一旦我意识到这一点,解决方案就很简单了。 使用WebApplicationFactory创建测试服务器,然后允许 OData 使用该应用程序中的IServiceProvider来构建我需要的 ODataQueryOptions。

缺点

意识到这个解决方案和你的TEntryPoint一样高效,所以如果你的应用程序需要很长时间才能启动,这将导致单元/集成测试需要很长时间才能运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM