开发笔记:用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. 通常编译亲测56Y国际象棋源代码,精仿56Y国际象棋完整的源代码下载!

    今天公布亲测通常应编译56Y国际象棋源代码,精仿56Y牌源代码.喜欢的能够拿去研究.论坛资源太多.我们会把好的资源都公布出来,同一时候欢迎很多其它的程序猿增加我们! 增加我们的共同学习交流!     ...

  2. vim代码折叠命令简短

    作者:zhanhailiang 日期:2014-10-18 1. 通过fdm实现代码折叠:set fdm=xxx 有下面6种方式实现折叠: |fold-manual| manual Folds are ...

  3. 玩转web之ajax(一)---使用表单的serialize()方法中文乱码解决

    有时候我们需要使用ajax提交去提交form的值,这样就需要使用serialize()去获取form的值,但这样获取的值如果有中文,会乱码,原因和解决方法如下: 原因:.serialize()自动调用 ...

  4. Timus 1777. Anindilyakwa 奇怪的问题计数

    The language of Australian aborigines anindilyakwa has no numerals. No anindilyakwa can say: "I ...

  5. 使用 Cordova+Visual Studio 创建跨平台移动应用(1)

    1简介 本章节是关于Visual Studio Tools for Apache Cordova的,目前此产品只发布了预览版.Visual Studio for Apache Cordova帮助熟悉V ...

  6. Please read “Security” section of the manual to find out how to run mysqld as root!错误解决(转)

    2016-03-12T15:40:45.717762Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please ...

  7. 应用层协议系列(两)——HTTPserver之http协议分析

    上一篇文章<抄nginx Httpserver设计与实现(一)--多进程和多通道IO现>中实现了一个仿照nginx的支持高并发的server.但仅仅是实现了port监听和数据接收.并没有实 ...

  8. Maven使用-利用Maven引入相关包(Struts2)

    根据上一篇的项目搭建,接下来引入需要使用Struts2相关包 1,如何利用maven往项目中引入包? maven就像一个导包助手一样,让它知道去哪里拿什么,他就会自动完成需要的包的搬运工作. (1), ...

  9. Java equals的一个坑

    public class StringEqualsObject { public static void main(String[] args) { String name="Tom&quo ...

  10. GUI (图形界面)知识点

    一:组件知识点 JTextField:    作用:  定义文本域,只支持单行输入.                使用:  定义文本域:  JTextField jtf=new JTextField ...