webentwicklung-frage-antwort-db.com.de

Unit Testing / Integration Testing-Web-API mit HttpClient in Visual Studio 2013

Es fällt mir schwer, meinen API-Controller mit Visual Studio 2013 zu testen. Meine eine Lösung verfügt über ein Web-API-Projekt und ein Testprojekt. In meinem Testprojekt habe ich einen Unit Test mit:

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

Ich bekomme immer eine 404. Ich habe versucht, meine API mit einer Instanz von Visual Studio (IIS Express) auszuführen und diesen Komponententest in einer anderen Instanz zu debuggen. Aber kein glück Ich habe überprüft, ob ich diese URL in einem Browser ablegen kann (wenn in einem Visual Studio ein Debugging ausgeführt wird), und es wird meine JSON-Antwort angezeigt. Aber ich kann nicht herausfinden, wie ich es mit meinem Unit-Test und HttpClient zum Laufen bringen kann. Ich habe versucht, online Beispiele zu finden, kann aber scheinbar keine finden. Kann jemand helfen?

PDATE 1: Ich habe versucht, eine Route hinzuzufügen, aber es ist nichts passiert.

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]

Hier ist mein API-Controller

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

PDATE Resolution: Ich konnte es zum Laufen bringen, wenn ich HttpClient ohne HttpServer Objekt neu einrichte. Ich müsste immer noch zwei Instanzen von VS ausführen. Ich führe meinen API-Code und einen anderen aus, um den Komponententest auszuführen.

Hier ist eine Arbeitsmethode.

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

Weiß jemand, warum es nicht mit einem HttpServer und einem HttpConfiguration funktioniert, die an HttpClient übergeben wurden? Ich habe viele Beispiele gesehen, die dies verwenden.

14
duyn9uyen

Unter Bezugnahme auf den folgenden Artikel konnte ich ...

ASP.NET-Web-API-Integrationstest mit In-Memory-Hosting

indem Sie mit einem HttpServer und einem HttpConfiguration arbeiten, die an HttpClient übergeben wurden. Im folgenden Beispiel habe ich ein einfaches ApiController erstellt, das Attributrouting verwendet. Ich habe HttpConfiguration so konfiguriert, dass Attributrouten zugeordnet werden, und habe es dann an das neue HttpServer übergeben. Das HttpClient kann dann den konfigurierten Server verwenden, um Integrationstestaufrufe an den Testserver zu tätigen.

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

Es war nicht erforderlich, dass eine andere VS-Instanz ausgeführt wurde, um den Controller zu integrieren.

Die folgende vereinfachte Version des Tests hat ebenfalls funktioniert

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

In Ihrem Fall müssen Sie sicherstellen, dass Sie den Server richtig für Ihre Web-API-Einrichtung konfigurieren. Dies würde bedeuten, dass Sie Ihre API-Routen mit dem Objekt HttpConfiguration registrieren müssen.

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