开发笔记:用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

用Owin Host实现脱离IIS跑Web API单元测试的更多相关文章

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

    今天在开发一个ASP.NET Web API项目写单元测试时,实在无法忍受之前的笨方法,决定改过自新. 之前Web API的单元测试需要进行以下的操作: 初始配置: 1)在IIS中创建一个站点指定We ...

  2. 使用Nancy.Host实现脱离iis的Web应用

    本篇将介绍如何使用Nancy.Host实现脱离iis的Web应用,在开源任务管理平台TaskManagerV2.0代码里面已经使用了Nancy.Host实现自宿主的Web应用.学习Nancy之前最好了 ...

  3. 以Self Host的方式来寄宿Web API

    Common类及实体定义.Web API的定义请参见我的上一篇文章:以Web Host的方式来寄宿Web API. 一.以Self Host寄宿需要新建一个Console控制台项目(SelfHost) ...

  4. 旅图beta版 asp.net web api 单元测试

    旅图 beta版 asp.net web api 单元测试 测试接口:http://120.27.7.115:1010/Help 测试目的 对每个接口单元进行测试,保证每个接口的可靠性. 单元描述 注 ...

  5. PCB 脱离IIS的Web应用

    在用.net Web编程中,我们写好的Web应用首选会挂在IIS上面,因为它足稳定并且功能齐全,但这不是我们唯一的选择,微软给我们提供了Owin组件,Web应该的宿主可以不再是IIS了,有了Owin后 ...

  6. 以Web Host的方式来寄宿Web API

    一.新建一个Common的类库项目并新建一个测试用的Contact实体类 namespace Common { public class Contact { public string Id { ge ...

  7. Web Api单元测试写法

    例如我们在Web Api项目中有个Controller public class SomeController : ApiController { public HttpResponseMessage ...

  8. Owin asp.net 脱离 IIS

    http://www.cnblogs.com/jesse2013/p/owin-webserver.html

  9. Web Api Self-Host

    今天有在研究SignalR, 发现SignalR可以使用Self-Host的方式,就突发奇想,Web Api是不是也可以使用Self-Host的方式寄宿在Console Application或者其他 ...

随机推荐

  1. Oracle安装过程物理内存检查及临时temp空间不足解决办法

    物理内存 – 此先决条件将测试系统物理内存总量是否至少为 922MB (944128.0KB). 预期值 : N/A 实际值 : N/A 错误列表: – 可用物理内存 PRVF-7531 : 无法在节 ...

  2. 使用require.js和backbone实现简单单页应用实践

    前言 最近的任务是重做公司的触屏版,于是再园子里各种逛,想找个合适的框架做成Web App.看到了叶大(http://www.cnblogs.com/yexiaochai/)对backbone的描述和 ...

  3. [Python]How to handle the exception in Python?

    This post demonstrates how to use try clause to handle the exceptions def test_exception(case=None): ...

  4. 【转】Qt事件循环与线程 二

    转自:http://blog.csdn.net/changsheng230/article/details/6153449 续上文:http://blog.csdn.net/changsheng230 ...

  5. 玩转Web之Json(四)---json与(Object/List/Map)的相互转化

    在做web应用时,经常需要将json转化成Object/list/map或者将Object/List/map转化成json,通过简单封装可以在写代码是减轻很多负担.本文将给出json转化的一系列方法. ...

  6. Zygote过程【3】——SystemServer诞生

    欢迎转载.转载请注明:http://blog.csdn.net/zhgxhuaa 在ZygoteInit的main()方法中做了几件大事.当中一件便是启动Systemserver进程.代码例如以下: ...

  7. 剖析html对标准标签和自定义标签闭合与不闭合渲染问题

    昨天在修改去年写的系统的时候无意中看到了当时写的一个利用标准标签未闭合在单元格内把整个单元格颜色渲染成红色的效果,如下: 当时的问题是从后台返回来的是个int整数而%是写在页面上的如图 这 时候就出现 ...

  8. React-Native入门

    React-Native入门指导之iOS篇 React-Native 入门指导系列教程目录 一.准备工作 (已完成) 二.项目介绍与调试 三.CSS样式与Flex布局 四.常用UI控件的使用 五.JS ...

  9. 【Android进阶】Android程序与JavaScript之间的简单调用

    本篇将讲解一个简单的Android与JavaScript之间的简单调用的小程序 效果图 工程结构 HTMLActivity.java代码 package com.example.javatojs; i ...

  10. 【Java基础】“数三退一”问题的代码实现

    现在有500个小孩,编号为0-499,手牵手连成一个圈,从第一个小孩开始"123123..."报数,数到三的小孩退出,求剩下的最后一个小孩的编号. public static vo ...