在 Visual Studio 2013 中使用 HttpClient 进行单元测试/集成测试 Web API
Posted
技术标签:
【中文标题】在 Visual Studio 2013 中使用 HttpClient 进行单元测试/集成测试 Web API【英文标题】:Unit Testing / Integration Testing Web API with HttpClient in Visual Studio 2013 【发布时间】:2016-05-27 05:19:18 【问题描述】:我很难用 Visual Studio 2013 测试我的 API 控制器。我的一个解决方案有一个 Web API 项目和一个测试项目。在我的测试项目中,我有一个单元测试:
[TestMethod]
public void GetProduct()
HttpConfiguration config = new HttpConfiguration();
HttpServer _server = new HttpServer(config);
var client = new HttpClient(_server);
var request = new HttpRequestMessage
RequestUri = new Uri("http://localhost:50892/api/product/hello"),
Method = HttpMethod.Get
;
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using (var response = client.SendAsync(request).Result)
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var test = response.Content.ReadAsAsync<CollectionListDTO>().Result;
我不断收到 404。我尝试使用 Visual Studio (IIS Express) 的一个实例运行我的 API,并尝试在另一个实例中调试此单元测试。但没有运气。我已经验证我可以将此 URL 放在浏览器中(当一个 Visual Studio 正在调试时)并且我看到了我的 JSON 响应。但我不知道如何让它与我的单元测试和HttpClient
一起工作。我试图在网上找到示例,但似乎找不到。有人可以帮忙吗?
更新 1: 我尝试添加路线,但没有任何反应。
HttpConfiguration config = new HttpConfiguration();
// Added this line
config.Routes.MapHttpRoute(name: "Default", routeTemplate: "api/product/hello/");
HttpServer _server = new HttpServer(config);
var client = new HttpClient(_server);
[...rest of code is the same]
这是我的 API 控制器
[HttpGet]
[Route("api/product/hello/")]
public IHttpActionResult Hello()
return Ok();
更新分辨率:
如果我在没有HttpServer
对象的情况下新建HttpClient
,我就能让它工作。不过,我仍然需要运行两个 VS 实例。 1 运行我的 API 代码,另一个运行单元测试。
这是一个工作方法。
[TestMethod]
public void Works()
var client = new HttpClient(); // no HttpServer
var request = new HttpRequestMessage
RequestUri = new Uri("http://localhost:50892/api/product/hello"),
Method = HttpMethod.Get
;
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using (var response = client.SendAsync(request).Result)
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
任何人都知道为什么它不能与 HttpServer
和 HttpConfiguration
传递到 HttpClient
一起工作吗?我见过很多使用这个的例子。
【问题讨论】:
可能没什么区别,但为什么不直接使用GetAsync呢? 您是否在启动时使用 OWIN 管道?您可能需要使用TestServer
。 blogs.msdn.microsoft.com/webdev/2013/11/26/…
我没有使用owin。
你使用的是什么版本的 asp.net-mvc web api?
您要测试的方法的代码在哪里?这看起来像是一个集成测试,因为您没有模拟/伪造任何依赖项。
【参考方案1】:
参考以下文章我能够做到...
ASP.NET Web API integration testing with in-memory hosting
通过使用 HttpServer
和 HttpConfiguration
传递到 HttpClient
。在以下示例中,我创建了一个使用属性路由的简单 ApiController
。我将HttpConfiguration
配置为映射属性路由,然后将其传递给新的HttpServer
。然后HttpClient
可以使用配置的服务器对测试服务器进行集成测试调用。
public partial class MiscUnitTests
[TestClass]
public class HttpClientIntegrationTests : MiscUnitTests
[TestMethod]
public async Task HttpClient_Should_Get_OKStatus_From_Products_Using_InMemory_Hosting()
var config = new HttpConfiguration();
//configure web api
config.MapHttpAttributeRoutes();
using (var server = new HttpServer(config))
var client = new HttpClient(server);
string url = "http://localhost/api/product/hello/";
var request = new HttpRequestMessage
RequestUri = new Uri(url),
Method = HttpMethod.Get
;
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using (var response = await client.SendAsync(request))
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
public class ProductController : ApiController
[HttpGet]
[Route("api/product/hello/")]
public IHttpActionResult Hello()
return Ok();
无需运行另一个 VS 实例即可对控制器进行集成测试。
以下简化版本的测试也同样有效
var config = new HttpConfiguration();
//configure web api
config.MapHttpAttributeRoutes();
using (var server = new HttpServer(config))
var client = new HttpClient(server);
string url = "http://localhost/api/product/hello/";
using (var response = await client.GetAsync(url))
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
在您的情况下,您需要确保正确配置服务器以匹配您的 Web api 设置。这意味着您必须使用 HttpConfiguration
对象注册您的 api 路由。
var config = new HttpConfiguration();
//configure web api
WebApiConfig.Register(config);
//...other code removed for brevity
【讨论】:
您是否可以向我发送此解决方案的副本?我从字面上复制了代码,但它似乎在我的解决方案中不起作用。所以我认为有一些不同的配置。我的项目属性具有在 IIS Express 下以端口号运行的项目。项目 url 有这个“localhost:50892”。我曾尝试在单元测试中使用端口但没有端口号,但没有成功。还是 404。 内存测试请求实际上并没有到达网络,因此与 IIS 或 IIS Express 无关。HttpServer
一个 DelegatingHandler
正在处理 HttpClient
正在发出的请求。不需要端口,默认值为http://localhost
,就像我的示例中一样。我从您的帖子中获取了确切的代码,只更改了 url 的主机并将控制器配置为使用属性路由。
复制我的答案中的确切单元测试类并在您的测试项目中运行它。它应该运行并通过。然后,您可以查看它是如何完成的,并尝试将相同的技术应用到您的实际测试中。没有多余的东西。您在那里看到的一切都是它的编写和测试方式。
我的猜测是MapHttpAttributeRoutes
在当前程序集中搜索具有 Route 特定属性的 ApiControllers。当我将 ProductController
从 Sample 项目复制到测试项目时,它起作用了。我可能需要查看 github 或 codeplex 上的源代码,看看该方法的作用。
我刚刚遇到了完全相同的问题,当我只调用config.MapHttpAttributeRoutes()
时,我的路由/控制器没有被发现。当我通过调用例如 WebApiConfig.Register(config);
添加对我的 WebApi 项目的显式引用时,它可以工作! (仅添加var ctrl = new ValuesController();
也可以!)我的猜测是这与未使用的程序集有关,运行时未加载。这意味着未加载 WebApi,因此不会扫描和发现路由/控制器以上是关于在 Visual Studio 2013 中使用 HttpClient 进行单元测试/集成测试 Web API的主要内容,如果未能解决你的问题,请参考以下文章
使用平台工具集 v120 (Visual Studio 2013) 在 Visual Studio 2015 中创建 C++/CLI 项目
Intel parallel studio 2017 集成在visual studio 2013 中,现在如何集成到visual studio 2015
在 Visual Studio 2013 中使用 Roslyn 编译器
在 Visual Studio 2013 中使用 angularjs 材料设计