unit testing/集成在Visual Studio 2013中使用HttpClient测试Web API

我很难用Visual Studio 2013测试我的API控制器。我的解决方案有一个Web API项目和一个测试项目。 在我的测试项目中,我有一个unit testing:

[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().Result; } } 

我一直得到404 。 我尝试使用一个Visual Studio实例(IIS Express)运行我的API,并尝试在另一个实例中调试此unit testing。 但没有运气。 我已经validation我可以将此URL放在浏览器中(当一个Visual Studio正在调试时),我看到了我的JSON响应。 但我无法弄清楚如何使用我的unit testing和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代码,另一个运行unit testing。

这是一种工作方法。

 [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和传递给HttpClientHttpConfiguration HttpClient ? 我见过很多使用它的例子。

参考以下文章,我能够做到……

使用内存中托管的ASP.NET Web API集成测试

通过使用传递给HttpClientHttpServerHttpConfiguration 。 在下面的示例中,我创建了一个使用属性路由的简单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 

关于使用HttpServer的问题,我能够使其工作如下:这是在.Net Framework中。 这也可用于测试WebAPI管道集成测试。

 public static HttpResponseMessage ConfigureAndAct(string relativeApiUrl, HttpMethod httpMethodType, string bodyForPostMethod, int userid) { var uri = new Uri(string.Concat("http://localhost:10022", relativeApiUrl)); // Todo:Find free port at runtime HttpResponseMessage response; using (HttpConfiguration config = new HttpConfiguration()) { config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; using (HttpRequestMessage request = new HttpRequestMessage() { Content = new StringContent(bodyForPostMethod, Encoding.UTF8, "application/json"), RequestUri = uri, Method = httpMethodType, }) { using (var server = new HttpServer(config)) { using (var client = new HttpClient(server)) { response = client.SendAsync(request, CancellationToken.None).Result; } } } } return response; } // Test GET ----------- //Act var response = ConfigureWebApiForTest.ConfigureAndAct(uriToTest, HttpMethod.Get, string.Empty, userId); var result = response.Content.ReadAsAsync().Result; //Assert Assert.IsTrue(response.StatusCode == HttpStatusCode.OK); Assert.IsNotNull(result); Assert.AreEqual(expectedUrl, result.SomeUrl); // Test POST ------------ // Act HttpResponseMessage response = ConfigureWebApiForTest.ConfigureAndAct(uriToTest, HttpMethod.Post, body, userId); //Assert Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);