2013-03-14 29 views
5

Nie mam dużego doświadczenia z .NET Web Api, ale pracuję nad tym od jakiegoś czasu, korzystając z tutoriala do aplikacji SPA Papai na Pluralsight. Aplikacja działa dobrze, ale rzeczą, z którą teraz walczę, jest testowanie POST kontrolerów.Jednostka testująca kontroler poczty .NET Web Api

Podążyłem za tym niesamowitym przewodnikiem na temat testowania kontrolerów internetowych. Jedynym problemem jest dla mnie testowanie metody POST.

Mój kontroler wygląda następująco:

[ActionName("course")] 
    public HttpResponseMessage Post(Course course) 
    { 
     if (course == null) 
      throw new HttpResponseException(HttpStatusCode.NotAcceptable); 
     try 
     { 
      Uow.Courses.Add(course); 
      Uow.commit(); 
     } 
     catch (Exception) 
     { 
      throw new HttpResponseException(HttpStatusCode.InternalServerError); 
     } 

     var response = Request.CreateResponse(HttpStatusCode.Created, course); 

     string uri = Url.Link(routeName: "ControllerActionAndId", 
     routeValues: new { id = course.Id }); 

     response.Headers.Location = new Uri(uri); 

     return response; 
    } 

A mój testów jednostkowych wygląda następująco:

[Test] 
    public void PostShouldReturnHttpResponse() 
    { 
     var populatedPostController = new CoursesController(new TestUOW()); 

     SetupPostControllerForTest(populatedPostController); 

     var course = new Course 
     { 
      Id = 12, 
      Author = new UserProfile() 
      { 
       Firstname = "John", 
       Lastname = "Johnson", 
      }, 
      Description = "Testcourse", 
      Title = "Test Title" 
     }; 

      var responses = populatedPostController.Post(course); 

      ObjectContent content = responses.Content as ObjectContent; 
      Course result = (Course)content.Value; 
      Assert.AreSame(result, course); 
    } 

Z funkcji pomocy:

public static void SetupPostControllerForTest(ApiController controller) 
    { 

     var config = new HttpConfiguration(); 
     var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/courses/course"); 
     var route = config.Routes.MapHttpRoute(
      name: "ControllerActionAndId", 
      routeTemplate: "api/{controller}/{action}/{id}", 
      defaults: null, 
      constraints: new { id = @"^\d+$" } 
     ); 

     var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "courses" }, { "action", "course" } }); 

     controller.ControllerContext = new HttpControllerContext(config, routeData, request); 
     controller.Request = request; 
     controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config; 
    } 

Kiedy debugować badanej jednostki , wygląda na to, że nie działa pod adresem:

 string uri = Url.Link(routeName: "ControllerActionAndId", 
     routeValues: new { id = course.Id }); 

     response.Headers.Location = new Uri(uri); //Exception because uri = null 

Wygląda na to, że adres Url.Link nie może znaleźć trasy.

Próbowałem również this przewodnik, ale naprawdę chcę mieć przykład powyżej do pracy.

Czy brakuje tu czegoś naprawdę podstawowego?

+1

Spróbuj dodać następujący wiersz na końcu 'SetupPostControllerForTest' method' controller.Request.Properties [HttpPropertyKeys.HttpRouteDataKey] = routeData;' – nemesv

+0

Tak, działa już teraz! Tak się dzieje, gdy jesteś zmęczony ... Dzięki! –

Odpowiedz

4

Tak, brakuje jednej linii w konfiguracji, o której wspomniał Nemesv.

Jak widać, konfigurowanie kontrolera tylko w celu korzystania z UrlHelper jest niezwykle skomplikowane. Z tego powodu staram się unikać używania UrlHelper w klasach kontrolerów. Zazwyczaj wprowadzam zewnętrzną zależność, aby ułatwić testowanie jak IUrlHelper, co pozwala mi naśmiewać zachowanie w teście jednostkowym.

public interface IUrlHelper 
    { 
     string Link(string routeName, object routeValues); 
     string Route(string routeName, object routeValues); 
    } 

    public class UrlHelperWrapper : IUrlHelper 
    { 
     UrlHelper helper; 

     public UrlHelperWrapper(UrlHelper helper) 
     { 
      this.helper = helper; 
     } 

     public string Link(string routeName, object routeValues) 
     { 
      return this.helper.Link(routeName, routeValues); 
     } 

     public string Route(string routeName, object routeValues) 
     { 
      return this.helper.Route(routeName, routeValues); 
     } 
    } 

I wstrzyknąć ten UrlHelperWraper w realnym Web API i makiety interfejsu IUrlHelper w testach. W ten sposób nie potrzebujesz całej złożonej konfiguracji z trasami.

Pozdrawiam, Pablo.

+0

Wow. Jak mogłem tęsknić, że: /. Wydaje się, że bardziej czysty sposób obsługi UrlHelper. Niezły, dzięki! –

+0

Witam @Pablo Cibraro, czy mógłbyś podać przykład na żywo, piszę moje testy jednostkowe po raz pierwszy dla aplikacji webowej i tworzę je w najbardziej zoptymalizowany sposób, w jaki trafiłem tutaj. Nie rozumiem, w jaki sposób korzystasz z pomocy URL i tego, co znalazłeś w pytaniu, które wyeliminowałeś za pomocą Pomocników URl. Każda Pomoc będzie bardzo ceniona –

Powiązane problemy