ASP.NET 5 使用 TestServer 进行单元测试
之前如果对 ASP.NET WebAPI 进行单元测试(HttpClient 发起请求,并且可调试 WebAPI),一般采用 Owin 的方式,具体参考:《开发笔记:用 Owin Host 实现脱离 IIS 跑 Web API 单元测试》
示例代码:
public class ValuesWebApiTest : IDisposable
{
private const string HOST_ADDRESS = "http://localhost:8001";
private IDisposable _webApp;
private HttpClient _httClient;
public AdTextUnitWebApiTest()
{
_webApp = WebApp.Start<Startup>(HOST_ADDRESS);
Console.WriteLine("Web API started!");
_httClient = new HttpClient();
_httClient.BaseAddress = new Uri(HOST_ADDRESS);
Console.WriteLine("HttpClient started!");
}
[Fact]
public async Task Get()
{
var response = await _httClient.GetAsync("/api/values");
if (response.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine(response.StatusCode);
Console.WriteLine((await response.Content.ReadAsAsync<HttpError>()).ExceptionMessage);
}
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var test = await response.Content.ReadAsStringAsync();
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
public void Dispose()
{
_httClient.Dispose();
_webApp.Dispose();
}
}
本来想在 ASP.NET 5 WebAPI 项目中,也用这一套测试代码,但发现并不适用,因为 ASP.NET WebAPI 2 和 ASP.NET 5 WebAPI 并不是特别一样,比如 Startup.cs 的配置等等,之前使用 WebApp.Start<Startup>(HOST_ADDRESS) 的方式启动 WebAPI 项目,而 ASP.NET 5 WebAPI 变成了这样的:
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
想用 WebApplication.Run 的方式替换掉 WebApp.Start,但发现并不可行,比如 args 的参数问题,自己想的有点简单了,后来 Google 搜索了一些资料,发现 ASP.NET 5 增加了 TestServer,自己找资料配置了很久,看别人的示例代码很简单,但我运行的时候就是各种报错,主要原因是程序包的版本不对,因为我是按照 project.json 的提示安装的,比如 Microsoft.AspNet.TestHost 这个程序包,提示最新版本为 1.0.0-rc2-15960,并且没有 1.0.0-rc1-final 版本,然后我就安装提示安装的 rc2,就报下面的异常:

异常信息:Could not load type 'Microsoft.AspNet.Builder.RequestDelegate' from assembly 'Microsoft.AspNet.Http.Abstractions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
根据提示,我以为异常原因是没有加载 Microsoft.AspNet.Http.Abstractions 程序集,然后又添加此程序集,重新运行发现还是报错。。。后面具体的过程就不记录了,反正坑很大,根本原因是 Microsoft.AspNet.TestHost 程序包的版本不对,应该安装 1.0.0-rc1-final 版本,我是后来无意间重启 VS2015 发现的。
下面贴一下 ASP.NET 5 进行单元测试的一些代码。
首先 ASP.NET 5 WebAPI 项目 Startup.cs 配置代码:
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Demo.WebApi
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseIISPlatformHandler();
app.UseStaticFiles();
app.UseMvc();
}
// Entry point for the application.
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}
ValuesWebApiTest 测试代码:
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Demo.WebApiTests
{
public class ValuesWebApiTest
{
public TestServer _server;
public ValuesWebApiTest()
{
_server = TestServer.Create(app =>
{
var env = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
var loggerFactory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
new CNBlogs.Ad.WebApi.Startup(env).Configure(app, env, loggerFactory);
}, services =>
{
services.AddMvc();
services.Configure();
});
}
}
[Fact]
public async Task Get()
{
var response = await _server.CreateClient().GetAsync("/api/values");
if (response.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine(response.StatusCode);
Console.WriteLine((await response.Content.ReadAsAsync<HttpError>()).ExceptionMessage);
}
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var test = await response.Content.ReadAsStringAsync();
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
project.json 配置代码:
{
"frameworks": {
"dnx451": { }
},
"dependencies": {
"Microsoft.AspNet.Mvc.WebApiCompatShim": "6.0.0-rc1-final",
"Microsoft.Net.Http": "2.2.29",
"Microsoft.AspNet.TestHost": "1.0.0-rc1-final",
"xunit": "2.1.0",
"xunit.runner.dnx": "2.1.0-rc1-build204"
},
"commands": {
"test": "xunit.runner.dnx"
}
}
运行测试成功,并且可以 Debug 调试,需要注意 using 引用(没用的我都去掉了),还有程序包的版本号。
注:如果 VS2015 Test Explorer 中找不到测试示例,需要安装最新的 xUnit 程序包。
"xunit": "2.2.0-beta2-build3256",
"xunit.runner.dnx": "2.1.0-rc2-build209"
xUnit 程序包地址:http://myget.org/gallery/xunit
参考资料:
- Integration testing ASP.NET 5 and ASP.NET MVC 6 applications | StrathWeb. A free flowing web tech monologue.
- Writing integration tests for ASP.NET 5
- Testing asp.net 5 vnext middleware from a TestServer - Stack Overflow
ASP.NET 5 使用 TestServer 进行单元测试的更多相关文章
- asp.net core 使用 TestServer 来做集成测试
asp.net core 使用 TestServer 来做集成测试 Intro 之前我的项目里的集成测试是随机一个端口,每次都真实的启动一个 WebServer,之前也有看到过微软文档上 TestSe ...
- ASP.NET Core 对Controller进行单元测试
单元测试对我们的代码质量非常重要.很多同学都会对业务逻辑或者工具方法写测试用例,但是往往忽略了对Controller层写单元测试.我所在的公司没见过一个对Controller写过测试的.今天来演示下如 ...
- Asp.Net MVC3中如何进行单元测试?
下面我们就以一个示例演示一下如何进行单元测试? public Model.UserInfo UpdateEntity(Model.UserInfo entity) { db.UserInfo.Atta ...
- ASP.NET 5 单元测试中使用依赖注入
相关博文:<ASP.NET 5 使用 TestServer 进行单元测试> 在上一篇博文中,主要说的是,使用 TestServer 对 ASP.NET 5 WebApi 进行单元测试,依赖 ...
- 单元测试 – ASP.NET MVC 4 系列
在开发可测试软件的过程中,单元测试已成为确保软件质量的一个不可或缺部分.测试驱动开发(Test-Driven Development,TDD)是编写单元测试的一种方法,采用该方法的开发人 ...
- Asp.Net Core 单元测试正确姿势
背景 ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,并且默认注入了很多服务,具体可以参考 官方文档, 相信只要使用过依赖注入框架的同学,都会对此有不同深入的理解,在此无需赘言. ...
- ASP.NET Core 入门(3)(单元测试Xunit及Shouldly的使用)
一.本篇简单介绍下在ASP.NET Core项目如何使用单元测试,例子是使用VS自带的Xunit来测试Web API接口,加上一款开源的断言工具Shouldly,方便写出更简洁.可读行更好的测试代码. ...
- Asp.Net Core 轻松学-利用xUnit进行主机级别的网络集成测试
前言 在开发 Asp.Net Core 应用程序的过程中,我们常常需要对业务代码编写单元测试,这种方法既快速又有效,利用单元测试做代码覆盖测试,也是非常必要的事情:但是,但我们需要对系统进行集 ...
- ASP.NET 5 RC1 升级 ASP.NET Core 1.0 RC2 记录
升级文档: Migrating from DNX to .NET Core Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0 RC2 Migrating ...
随机推荐
- asp.net mvc添加多条数据到数据库
mvc的视图太强大了,个人刚刚接触.(初级菜鸟,懂的不多,往大神们指点)需求是,客户点击添加按钮弹出一个框选择产品后直接添加到表单中,在表单可以自己更改产品的数量,以及一些信息.mvc表单提交的时候只 ...
- getComputedStyle的应用
后面有例子,所以把HTML,CSS样式写在前面 HTML结构: <div id="myDiv" style="background-color: lightseag ...
- tornado web 框架的认识
tornado 简介 1,概述 Tornado就是我们在 FriendFeed 的 Web 服务器及其常用工具的开源版本.Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的 ...
- springMVC+spring+hibernate 框架整合实例
先说一下流程思路: 流程讲解1:首先访问会先定位到控制器.这就用到了过滤器配置文件"spring-mvc.xml".这个文件负责定义控制器的包路径.视图的格式等.其次从" ...
- 用c#创建支持多语言的WinForm应用程序
实现多语言的方法可能有使用资源文件,或者配置xml两种方法吧.没时间研究过多,学习了一下使用资源文件的方法,成功了. 在.net2.0 中,m$ 为我们提供了一种简单方便的方法, 使用资源文件 1.新 ...
- Permission denied user=hadoop access=WRITE inode=root rootsupergroup rwxr
有段时间没有写了,反正我写的都是跟流水账一样.不为别人看,当然,其中也记录了很多我踩过的坑,可能也能给别人提个醒.最重要的是:这是我学习的记忆 上面的错误是由于我将reducer的输出目录设置在hdf ...
- java06
阅读并运行示例PassArray.java,观察并分析程序输出的结果 小结:引用传递.如果方法中有代码则更改了数组元素的值,因为引用时传递的是地址. 阅读程序WhatDoesThisDo.java, ...
- 用jdbc访问二进制类型的数据
package it.cast.jdbc; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; impor ...
- 论如何在手机端web前端实现自定义原生控件的样式
手机开发webapp的同学一定遇到过这样问题,如何为丑极了的手机元素应用自定义的样式.首先,要弄清楚为什么要定义手机原生控件的样式,就需要看看手机的那些原生框样式的丑陋摸样: android: ios ...
- 走向面试之数据库基础:二、SQL进阶之case、子查询、分页、join与视图
一.CASE的两种用法 1.1 等值判断->相当于switch case (1)具体用法模板: CASE expression WHEN value1 THEN returnvalue1 WHE ...