Unidad de prueba / API de web de prueba de integración con HttpClient en Visual Studio 2013

Me cuesta mucho probar mi controlador API con Visual Studio 2013. Mi única solución tiene un Proyecto de API web y un proyecto de Prueba. En mi proyecto de prueba, tengo una prueba de unidad con esto:

[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; } } 

Sigo recibiendo un 404 . He intentado ejecutar mi API con una instancia de Visual Studio (IIS Express) y tratando de depurar esta prueba de unidad en otra instancia. Pero no hay suerte. He verificado que puedo poner esta URL en un navegador (cuando un Visual Studio está depurando) y veo mi respuesta JSON. Pero no puedo averiguar cómo hacer que funcione con mi prueba de unidad y HttpClient . He intentado encontrar ejemplos en línea pero parece que no puedo encontrar uno. ¿Alguien puede ayudar?

ACTUALIZACIÓN 1: Intenté agregar una ruta pero no sucedió nada.

 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] 

Aquí está mi controlador de API

 [HttpGet] [Route("api/product/hello/")] public IHttpActionResult Hello() { return Ok(); } 

Resolución de ACTUALIZACIÓN: Pude hacer que funcionara si hago HttpClient sin un objeto HttpServer . Aun así necesitaría tener dos instancias de VS en ejecución. 1 ejecutando mi código API y otro para ejecutar la prueba de unidad.

Aquí hay un método de trabajo.

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

¿Alguien sabe por qué no funciona con un HttpServer y un HttpConfiguration pasado a HttpClient ? He visto muchos ejemplos que usan esto.

Haciendo referencia al siguiente artículo pude hacer …

Pruebas de integración de la API web de ASP.NET con alojamiento en memoria

trabajando con un HttpServer y una HttpConfiguration pasa a HttpClient . En el siguiente ejemplo, creé un ApiController simple que usa enrutamiento de atributos. Configuré HttpConfiguration para asignar rutas de atributos y luego lo pasé al nuevo HttpServer . El HttpClient puede usar el servidor configurado para realizar llamadas de prueba de integración al servidor de prueba.

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

No era necesario tener otra instancia de VS en ejecución para probar la integración del controlador.

La siguiente versión simplificada de la prueba funcionó también

 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); } } 

En su caso, debe asegurarse de que está configurando el servidor correctamente para que coincida con la configuración de su API web. Esto significaría que tienes que registrar tus rutas api con el objeto HttpConfiguration .

 var config = new HttpConfiguration(); //configure web api WebApiConfig.Register(config); //...other code removed for brevity 

Con respecto a su pregunta sobre el trabajo con HttpServer, pude hacer que funcione como se muestra a continuación: Esto está en .Net Framework. Esto también se puede utilizar para probar las pruebas de integración de canalización de 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);