.netcore持续集成测试篇之搭建内存服务器进行集成测试一
在web项目里,我们把每一层的代码的单元测试都通过并不代表程序能正常运行,因为这个过程缺失了http管道,很多时候我们还还需要把项目布在iis环境中或者在vs里启动iis express服务器进行集成测试.对于返回view的的方法我们通常是在浏览器中输入地址进行测试,对于返回数据的方法则使用诸如postman,fiddler,httpMaster pro,http debugger等工具进行测试.在这些工具中,postman相对好用,不但提供了测试数据的分组功能,还可以编写脚本来完成一些自动化工作,比如自动添加固定http头等.然而即便诸如postman这么强大,依赖有很多不方便的地方.一旦方法过多,管理起来很不方便.并且构造复杂json或者formdata数据更是让人心力绞悴,稍有一点格式错误就导致整个测试通不过,严重影响对错误点位置的判断.更为重要的一点是,我们不论是在页面中输入地址,还是使用postman工具更多的是被动的去解决问题,也就是说等错误出现了以后我们才去测试相应的方法,很少见有谁使用postman把所有方法全部都跑一遍.
幸运的是.微软在把.net升级到.net core之后,asp.net core 可以搭建一个内存服务器来完成集成测试,这样我们便可以不依赖于特定环境来测试我们的代码.这样我们就在项目发布前可以先运行一下集成测试确保各方法都是可访问的,减少项目上线后出现一些简单错误的机率.
下面我们介绍如何搭建集成测试环境
产生我们使用VisualStudio自带的模板创建一个Asp.net core web项目,在出现的对话框选项中选择mvc(当然也可以不使用mvc项目,这里不了演示方便起见).新建完mvc项目后,默认会有一个HomeController,想必大家都很熟悉了.此时我们再新建一个HelloWorld控制器,这个控制器目前只有一个Hello方法,代码如下
public class HelloWorldController : Controller
{
public IActionResult Hello()
{
return Content("Hello,World");
}
}
然后我们使用VisualStudio自带的Xunit模板创建一个测试项目(新建项目的时候切换到.net core标签,里面有Xunit测试项目模板)
此时,在测试项目里需要添加Microsoft.AspNetCore.TestHost Nuget包才可以进行集成测试.
需要注意的是,这个包要安装在测试项目里,而不是core Mvc项目里
我们新建一个名为mvc20的测试类,代码如下
public class mvc20
{
private readonly HttpClient _client;
public mvc20()
{
var builder = new WebHostBuilder()
.UseContentRoot(@"E:\personal project\newTest2018\ConsoleApp1\CoreMvc")
.UseEnvironment("Development")
.UseStartup<CoreMvc.Startup>();
var server = new TestServer(builder);
_client = server.CreateClient();
}
[Fact]
public async Task SimpleGet()
{
var response = await _client.GetAsync("/HelloWorld/Hello");
response.EnsureSuccessStatusCode();
var responseStr = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello,World", responseStr);
}
}
配置详解
下面我们来详细分析这段代码
我们先来看构造函数里的代码,这里的第一部分是创建一个WebHostBuilder,如果了解过.net core的同事可能对这段代码感到很熟悉,其实mvc项目也是通过WebHostBuilder创建一个webhost,我们打开刚创建的mvc项目,打开program入口类可以看到如下代码
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
可以看到BuildWebHost方法里面使用了WebHost类来创建一个默认WebHostBuilder,这个方法里面也有UseStartup方法,其实像亲朋ContentRoot,UseEnvironment这些方法也可以在mvc项目里用,早期的.net core 项目模板生成的方法确实是这样的,只是在.net core 2.0进行了更进一步的抽象,ContentRoot路径,默认工作环境都按照惯例提供,不再需要手动指定.但是测试项目的工作环境和mvc项目的运行环境并不在同一个目录,因此这里需要手工指定.
UseContentRoot
此方法用于指定项目运行时资源文件的根目录,通常情况下是创建项目的目录,以上目录大家根据创建项目的路径来选择,不要盲目拷贝以上代码.
UseEnvironment
此方法用于指定项目的运行环境,这里我们指定为Development环境,这个环境是开发环境约定的默认环境,至于为什么需要指定工作环境,因为很多时候开发环境和线上环境中使用到的组件是不一样的,这在.net core项目里尤其明显,比如说线上环境中我们使用的是正式的EntityFramework,而在工作环境下为了效率我们更倾向使用一个内存EntityFramework.还有一些工具类的框架只是在开发环境中使用的,线上环境并不需要它.
这个概念可能很容易理解,但是相信大家仍然看的一头蒙圈,为什么是Development,而不是Develop,debug呢,其实这个变量名是在mvc项目下的Properties里面的launchSettings.json
里定义的.
因此如果我们提供的参数是"Development",mvc项目启动的时候就把它和这个文件匹配,如果匹配成功则当前工作环境就是Development环境.
到于它是怎么用,可以查看Startup.cs文件,里面会注入IHostingEnvironment 对象实例,其中里面的env.IsDevelopment就是通过这个值来判断当前工作环境是否是Development环境,如果是工作环境,我们可以添加一些只有在工作环境中使用的代码.
UseStartup
此方法用于指定一个Startup文件,Startup文件在mvc5项目里也有,主要是关于中间件的配置,只是mvc5在启动的时候自动调用一个名为Startup的文件(mvc5项目里这个文件不是必须的),而.net core里显式指定一个startup文件,这样就必须指定一个startup文件(名称不必须是startup,可以是任意名,这里是显式指定的,因此程序中能找到). net core项目里startup文件必须指定否则整个项目就是一个普通操控台应该程序,没法实现http功能,不论是mvc,webapi还是基本的http请求在.net core里都作为一个中间件,要使用必须配置.
回到测试方法里,这个startup文件直接指定为mvc项目里的startup文件即可,并且必须要这样,如果测试环境中的startup文件和mvc项目里的不一样测试就显得没有意义了.
TestServer
在测试环境里通过new方式创建一个TestServer,构造函数接收一个IWebHostBuilder类型的参数,我们把上面创建的WebHostBuilder传入即可.
创建HttpClient
TestServer对象可以创建一个HttpClient对象,利用HttpClient对象我们便可以构建Http请求了.
需要说明的是这个HttpClient并没什么特殊的,它就是System.net.http下的httpclient,想必大家多少都用到过.
下面我们来看测试方法,测试方法主要就是通过HttpClient来发送Http请求,这里的代码相信大家都并不陌生.
需要特别注意的是,这个测试方法和以往的不太相同,是一个async Task标识的异步方法,之所以要使用异步方法是因为HttpClient里的方法都是异步的,如果尝试使用同步的方法获取结果,很容易造成死锁.可能大家在工作中也确实使用过xxx.Result来同步阻塞获取异步结果,并且能正确返回真,但是阻塞HttpClient里的异步方法很多时候都会造成死锁.至于原因大家可以查看这篇文章
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
小贴士,如何在Main方法里面调用异步函数,C# 7.1之前版本的Main方法是不支持异步Main方法的,这给测试异步方法带来了很大的不便,c# 7.1开始支持异步Main方法,我们可以把Main方法标识为Async Task Main(string[] args).然后我们在visual studio里对着项目右键点击属性,在Build标签下选择
高级
,弹出的对话框里语言版本下拉列表选择c# 7.1或者更高(写本文时,VisualStudio最高支持C# 7.3).这样异步Main方法便能编译通过了.
下面言归正传,测试方法里的代码相必大家都很熟悉了,这里有一点可能有些同事没有遇到过那就是EnsureSuccessStatusCode
从字面上看它的意思是保证成功状态,实际上它并不是保证请求一定能够返回成功,而是返回的状态码不是200的时候就抛出一个异常.
需要注意的是
EnsureSuccessStatusCode
请求返回的必须是200才能通过,201,204这样的状态码也会抛出异常.大家在开发过程中一定要根据实际情况来决定是否使用它.一般情况下前后端分离的项目里很多项目组都对http请求返回的结果进行了封闭,不管成功或者失败都返回200,具体成功失败是通过一个额外的其它字段来确实的.这种情况下需要使用EnsureSuccessStatusCode,如果有对外接口很多时候会返回201,204,304,403等http状态,这时候如果 使EnsureSuccessStatusCode则结果不是我们期待的.
.netcore持续集成测试篇之搭建内存服务器进行集成测试一的更多相关文章
- linux篇-centos7搭建apache服务器(亲测可用)
1安装apache yum install httpd httpd-devel -y 2开启服务器 systemctl start httpd.service 3开机自启 systemctl enab ...
- linux篇-CentOS7搭建NTP服务器
1查看服务器.客户端操作系统版本 2查看服务器是否安装ntp 3如果没有安装 4安装完成后重新查看服务器是否安装ntp 5查看ntp服务器状态 6修改配置文件 注释 #server 0.centos. ...
- linxu篇-centos搭建ftp服务器
1安装vsftpd 2备份配置文件 3修改配置文件 vi /etc/vsftpd/vsftpd.conf anonymous_enable=NO #允许匿名用户访问为了安全选择关闭 local_ena ...
- 【前端】CentOS 7 系列教程之三: 搭建 git 服务器
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/linux_3.html 上一篇我们安装好了git,这一篇我们搭建git服务器 创建一个用户组 groupadd g ...
- .netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求
系列目录 Web项目中,很多与用户数据交互的请求都是Post请求,想必大家都用过HttpClient构造过post请求,这里并不对HttpClient做详细介绍,只介绍一些常用的功能.并结合AutoF ...
- .netcore持续集成测试篇之开篇简介及Xunit基本使用
系列目录 为了支持跨平台,微软为.net平台提供了.net core test sdk,这样第三方测试框架诸如Nunit,Xunit等只需要按照sdk提供的api规范进行开发便可以被dotnet cl ...
- .NET持续集成与自动化部署之路第一篇——半天搭建你的Jenkins持续集成与自动化部署系统
.NET持续集成与自动化部署之路第一篇(半天搭建你的Jenkins持续集成与自动化部署系统) 前言 相信每一位程序员都经历过深夜加班上线的痛苦!而作为一个加班上线如家常便饭的码农,更是深感其痛 ...
- 持续集成之二:搭建SVN服务器(subversion)
安装环境 Red Hat Enterprise Linux Server release 7.3 (Maipo) jdk1.7.0_80 subversion-1.10.3.tar.gz apr-1. ...
- iOS开发网络篇—搭建本地服务器
iOS开发网络篇—搭建本地服务器 一.简单说明 说明:提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提示:提前准备好的软件 apache- ...
随机推荐
- Django随机生成验证码图片
PIL简介 什么是PIL PIL:是Python Image Library的缩写,图像处理的模块.主要的类包括Image,ImageFont,ImageDraw,ImageFilter PIL的导入 ...
- JsonUtil(基于Jackson的实现)
JsonUtil(基于Jackson的实现) 前言: 其实,我一直想写一个有关Util的系列. 其中有四个原因: Util包作为项目的重要组成,是几乎每个项目不可或缺的一部分.并且Util包的Util ...
- 浅入深出Vue:注册
基本布局已经有了, 现在我们来开始做我们的注册页面~ 当然需要注册才能发表文章啊(糟老头子坏得很, 我可以只有我一个人能发啊). 这里我们设定只有注册才能发表文章,也就淡化了管理员这个概念.在开发中先 ...
- Scratch3 二次开发系列
Scratch3.0来啦!!! Scratch做为图像化编程的首选语言,拖过积木块搭建实现动画游戏的制作.Scratch3添加了音乐.画笔.视频侦测.文字朗读.翻译等选择性下载扩展积木,可实现积 ...
- 简单学习之json格式说明
json格式说明: 1.对象是一个无序的“‘名称/值’对”集合. (1)一个对象以“{”(左括号)开始,“}”(右括号)结束. (2)每个“名称”后跟一个“:”(冒号): (3)“‘名称/值’ 对”之 ...
- bzoj1584 9.20考试 cleaning up 打扫卫生
1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 549 Solved: 38 ...
- 这样子来理解C语言中指针的指针
友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...
- VC win32 static library静态链接库简单示例
中午在宿舍闲来没事,看到网上一篇帖子,关于静态链接库的英文示例.它在.Net上开发,我将其移到VC上开发,因此对其代码做了相应修改.帖子内容如下:(代码我已修改).原帖见:http://msdn.mi ...
- 跨站脚本攻击(存储型xss)笔记(二)
测试目标字段:页面下方的红色框位置. 由于编辑状态是编辑器,所以有可能出现跨站! 我插了个input然而并没有当代码执行 可能有些测试人员就认为被过滤掉了,因为尝试了各种尖括号.js事件.转义.编码等 ...
- matlab考试重点详解
此帖是根据期末考试复习重点补充完成, 由于使用word编辑引用图片和链接略有不便, 所以开此贴供复习及学习使用.侵删 复习要点 第一章 Matlab的基本概念,名称的来源,基本功能,帮助的使用方法 1 ...