zoukankan      html  css  js  c++  java
  • 用Owin Host实现脱离IIS跑Web API单元测试

    开发笔记:用Owin Host实现脱离IIS跑Web API单元测试

     

    今天在开发一个ASP.NET Web API项目写单元测试时,实在无法忍受之前的笨方法,决定改过自新。

    之前Web API的单元测试需要进行以下的操作:

    初始配置:

    1)在IIS中创建一个站点指定Web API项目

    2)在hosts加上该站点的IP地址解析

    每次修改代码:

    3)修改代码之后按F6编译

    4)用TestDriven.Net运行单元测试

    一看就知道这个方法好土、好笨、好受罪。理想的方式应该是:无需任何初始配置,修改代码之后无需按F6编译,直接运行单元测试,一步完成操作。

    今天在受不了旧方式的折磨、经不起理想方式的诱惑的情况下,下定决心要解决这个问题,最终通过Owin Host实现了,通过这篇博文分享一下。

    用Owin Host实现的思路很简单,就是在单元测试中以Owin Host运行ASP.NET Web API站点,然后单元测试代码直接请求这个Owin Host站点进行测试。

    我们的Web API项目是基于ASP.NET 4.5 + ASP.NET Web API 5.2.3开发的,没有OWIN相关的代码,所以先要在Web API项目中添加一些代码 ,以让Owin Host能够加载之。

    首先nuget安装Owin包包(IAppBuilder在此包中):

    PM> Install-Package Owin

    然后添加Startup.cs:

    复制代码
    public class Startup
    {
        public void Configuartion(IAppBuilder app)
        {
        }
    }
    复制代码

    接着nuget安装Microsoft.AspNet.WebApi.Owin包包(app.UseWebApi扩展方法在此包中)

    PM> Install-Package Microsoft.AspNet.WebApi.Owin

    在Startup.Configuratrion方法中添加代码,调用WebApiConfig.Register方法(这个是之前已经实现的,路由配置就在其中)配置HttpConfiguration,然后将之注册到OWIN的管线中。

    复制代码
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var configuraton = new HttpConfiguration();
            WebApiConfig.Register(configuraton);
            app.UseWebApi(configuraton);
        }
    }
    复制代码

    Web API项目只需这样简单改造一下,就可以支持Owin Host,无任何副作用,不影响用IIS部署站点。

    单元测试代码的改造也很简单,只需在跑测试之前用Microsoft.Owin.Hosting中的WebApp.Start()方法加载Web API站点。

    首先nuget安装Owin Host的包包:

    PM> Install-Package Microsoft.Owin.Hosting
    PM> Install-Package Microsoft.Owin.Host.HttpListener

    接着在测试类的构造函数中用WebApp.Start()启动Web API站点:

    复制代码
    public class CommentsWebApiTest : IDisposable
    {
        private const string HOST_ADDRESS = "http://localhost:8001";
        private IDisposable _webApp;
        public CommentsWebApiTest()
        {
            _webApp = WebApp.Start<Startup>(HOST_ADDRESS);
            Console.WriteLine("Web API started!");
        }
    
        public void Dispose()
        {
            _webApp.Dispose();
        }
    }
    复制代码

    然后就可以脱离IIS无比轻松地进行Web API的单元测试了。

    下面来实际体验一下:

    1)在Web API项目中实现一个ApiController

    复制代码
    public class CommentsController : ApiController
    {
        [Route("blogposts/{postId}/comments")]
        public async Task<IHttpActionResult> Get(int postId)
        {
            var comments = new Comment[] { new Comment {
                PostId = postId,
                Body = "Coding changes the world1" } };
            return Ok<Comment[]>(comments);
        }
    }
    复制代码

    2)编写基于Owin Host跑Web API站点的单元测试代码

    复制代码
    public class CommentsWebApiTest : IDisposable
    {
        private const string HOST_ADDRESS = "http://localhost:8001";
        private IDisposable _webApp;
        private HttpClient _httClient;
    
        public CommentsWebApiTest()
        {
            _webApp = WebApp.Start<Startup>(HOST_ADDRESS);
            Console.WriteLine("Web API started!");
            _httClient = new HttpClient();
            _httClient.BaseAddress = new Uri(HOST_ADDRESS);
            Console.WriteLine("HttpClient started!");
        }
    
        public void Dispose()
        {
            _httClient.Dispose();
            _webApp.Dispose();
        }
    
        [Fact]
        public async Task GetComments()
        {
            var postId = 1;
            var response = await _httClient.GetAsync($"/blogposts/{postId}/comments");
            if(response.StatusCode != HttpStatusCode.OK)
            {
                Console.WriteLine(await response.Content.ReadAsStringAsync());
            }
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            var comments = await response.Content.ReadAsAsync<Comment[]>();
            Assert.NotEmpty(comments);
            Assert.Equal(postId, comments[0].PostId);
            Assert.Equal("Coding changes the world", comments[0].Body);
        }
    }
    复制代码

    注:除了nuget安装Microsoft.Owin.Hosting与Microsoft.Owin.Host.HttpListener包包,还要安装Microsoft.AspNet.WebApi.Client包包(ReadAsAsync<Comment[]>在此包中)。

    3)运行单元测试:在单元测试方法中点击鼠标右键并点击Run Test(s)(用的是TestDriven.Net,会在单元测试前自动进行编译)

    4)查看单元测试结果,验证测试Web API的理想方式是否实现:

    Output from WebApiTests.CommentsWebApiTest.GetComments:
      Web API started!
      HttpClient started!
    
    1 passed, 0 failed, 0 skipped, took 4.91 seconds (xUnit.net 1.9.2 build 1705).

    测试通过!理想方式实现!

    这次经历再次证明了,当有一个问题影响你写代码的乐趣时,一定要尽早下定决心解决它,否则它浪费的时间很可能是解决这个问题所需时间的n倍,而且很多时候解决一个问题的难易程度取决于你下的决心有多大。

    【更新】

    需要注意一个地方,在单元测试中以owin host运行web api站点时,配置信息(比如数据库连接字符串)是从单元测试项目的app.config中读取,而不是从web api项目的web.config中读取,所以要将web.config中的相关配置复制到app.config中。

    【参考资料】 

    ASP.NET Web API Integration Testing with One Line of Code

  • 相关阅读:
    把C语言的指针按在地上摩擦!
    组合索引相关介绍
    ConcurrentModificationException异常
    chat和varchar的区别?
    二进制部署K8S集群(二十三)addons之安装部署dashboard
    二进制部署K8S集群(二十二)addons之安装部署ingress
    二进制部署K8S集群(二十一)addons之flanneld优化SNAT规则
    二进制部署K8S集群(二十)K8s服务暴露之NodePort型Service
    二进制部署K8S集群(十九)addons之安装部署coredns
    二进制部署K8S集群(十八)addons之flannel三种模型安装部署详解
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4743832.html
Copyright © 2011-2022 走看看