web-dev-qa-db-fra.com

Test unitaire / Test d'intégration API Web avec HttpClient dans Visual Studio 2013

J'ai du mal à tester mon contrôleur d'API avec Visual Studio 2013. Ma seule solution a un projet d'API Web et un projet de test. Dans mon projet de test, j'ai un test unitaire avec ceci:

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

Je reçois toujours un 404. J'ai essayé d'exécuter mon API avec une instance de Visual Studio (IIS Express) et d'essayer de déboguer ce test unitaire dans une autre instance. Mais pas de chance. J'ai vérifié que je peux mettre cette URL dans un navigateur (lorsqu'un Visual Studio débogue) et je vois ma réponse JSON. Mais je n'arrive pas à comprendre comment le faire fonctionner avec mon test unitaire et HttpClient. J'ai essayé de trouver des exemples en ligne mais je n'arrive pas à en trouver un. Quelqu'un peut-il aider?

MISE À JOUR 1: J'ai essayé d'ajouter un itinéraire mais rien ne s'est produit.

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]

Voici mon API Controller

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

MISE À JOUR Résolution: J'ai pu le faire fonctionner si je renouvelais HttpClient sans objet HttpServer. J'aurais néanmoins besoin d'avoir deux instances de VS en cours d'exécution. 1 exécutant mon code API et un autre pour exécuter le test unitaire.

Voici une méthode de travail.

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

Quelqu'un sait pourquoi cela ne fonctionne pas avec un HttpServer et un HttpConfiguration passés dans HttpClient? J'ai vu de nombreux exemples qui utilisent cela.

14
duyn9uyen

Référençant l'article suivant que j'ai pu faire ...

Test d'intégration de l'API Web ASP.NET avec hébergement en mémoire

en travaillant avec un HttpServer et un HttpConfiguration passés dans HttpClient. Dans l'exemple suivant, j'ai créé un simple ApiController qui utilise le routage d'attributs. J'ai configuré le HttpConfiguration pour mapper les routes d'attributs, puis je l'ai passé au nouveau HttpServer. HttpClient peut ensuite utiliser le serveur configuré pour effectuer des appels de test d'intégration au serveur de test.

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

Il n'était pas nécessaire d'avoir une autre instance de VS en cours d'exécution pour tester l'intégration du contrôleur.

La version simplifiée suivante du test a également fonctionné

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

Dans votre cas, vous devez vous assurer que vous configurez le serveur correctement pour correspondre à la configuration de votre API Web. Cela signifie que vous devez enregistrer vos routes api avec l'objet HttpConfiguration.

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