2014-10-17 2 views
0

내 컨트롤러를 단위 테스트하려고하는데이 컨트롤러가 포함 된 UrlHelper 개체를 사용하자마자 ArgumentNullException을 던집니다.단위 테스트 WebApi의 WebApi 컨트롤러

내가 시험에 노력하고있어 행동이 하나입니다

public HttpResponseMessage PostCommandes(Commandes commandes) 
    { 
     if (this.ModelState.IsValid) 
     { 
      this.db.AddCommande(commandes); 

      HttpResponseMessage response = this.Request.CreateResponse(HttpStatusCode.Created, commandes); 

      // this returns null from the test project 
      string link = this.Url.Link(
       "DefaultApi", 
       new 
       { 
        id = commandes.Commande_id 
       }); 
      var uri = new Uri(link); 
      response.Headers.Location = uri; 

      return response; 
     } 
     else 
     { 
      return this.Request.CreateResponse(HttpStatusCode.BadRequest); 
     } 
    } 

내 시험 방법은 다음과 같습니다

[Fact] 
    public void Controller_insert_stores_new_item() 
    { 
     // arrange 
     bool isInserted = false; 
     Commandes item = new Commandes() { Commande_id = 123 }; 
     this.fakeContainer.AddCommande = (c) => 
      { 
       isInserted = true; 
      }; 
     TestsBoostrappers.SetupControllerForTests(this.controller, ControllerName, HttpMethod.Post); 

     // act 
     HttpResponseMessage result = this.controller.PostCommandes(item); 

     // assert 
     result.IsSuccessStatusCode.Should().BeTrue("because the storage method should return a successful HTTP code"); 
     isInserted.Should().BeTrue("because the controller should have called the underlying storage engine"); 

     // cleanup 
     this.fakeContainer.AddCommande = null; 
    } 

그리고 here 바와 같이 SetupControllerForTests 방법은 이것이다 :

public static void SetupControllerForTests(ApiController controller, string controllerName, HttpMethod method) 
    { 
     var request = new HttpRequestMessage(method, string.Format("http://localhost/api/v1/{0}", controllerName)); 
     var config = new HttpConfiguration(); 
     var route = WebApiConfig.Register(config).First(); 
     var routeData = new HttpRouteData(route, new HttpRouteValueDictionary 
               { 
                { 
                  "controller", 
                  controllerName 
                } 
               }); 

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

이것은 WebApi2에 대한 문서화 된 문제입니다. 예를 들어 here에 대해 자세히 읽어보십시오 ("링크 생성 테스트"). 기본적으로 사용자 정의 ApiController.RequestContext을 설정하거나 컨트롤러의 Url 속성을 조롱합니다. (: Microsoft.AspNet.WebApi 4.0.20710.0/WebApi.Core.4.0.30506.0 Nuget 패키지) 때문에, ApiController.RequestContext이 존재하지 않으며, MOQ는 UrlHelper 클래스를 조롱 할 수

문제는 WebApi의 내 버전,이다 그것을 모의해야 할 방법 (Link)은 무시할 수 없거나, (나는 그것에 머 무르지 않았다.) 그런 식이다. 왜냐하면 나는 WebApi를 사용하고 있기 때문입니다. 그러나 블로그에 게시 된 코드는 V1을 사용합니다. 그래서 왜 작동하지 않는지, 그리고 무엇보다도 어떻게 작동하게 할 수 있는지 이해하지 못합니다.

감사합니다.

+0

테스트에서'Link' 메소드를 반환 하시겠습니까? – lockstock

+0

나는별로 관심이 없다. – thomasb

답변

1

원래 게시물 이후에 링크 된 문서가 업데이트되었지만 UrlHelperLink 메소드를 조롱 한 예가 나와 있는지 확실하지 않습니다.

[TestMethod] 
public void PostSetsLocationHeader_MockVersion() 
{ 
    // This version uses a mock UrlHelper. 

    // Arrange 
    ProductsController controller = new ProductsController(repository); 
    controller.Request = new HttpRequestMessage(); 
    controller.Configuration = new HttpConfiguration(); 

    string locationUrl = "http://location/"; 

    // Create the mock and set up the Link method, which is used to create the Location header. 
    // The mock version returns a fixed string. 
    var mockUrlHelper = new Mock<UrlHelper>(); 
    mockUrlHelper.Setup(x => x.Link(It.IsAny<string>(), It.IsAny<object>())).Returns(locationUrl); 
    controller.Url = mockUrlHelper.Object; 

    // Act 
    Product product = new Product() { Id = 42 }; 
    var response = controller.Post(product); 

    // Assert 
    Assert.AreEqual(locationUrl, response.Headers.Location.AbsoluteUri); 
} 
0

따라서 UrlHelper.Link 메소드를 조롱해야합니다. Typemock Isolator (주어진 링크의 테스트 예제)로 쉽게 수행 할 수 있습니다 :

[TestMethod, Isolated] 
public void PostSetsLocationHeader_MockVersion() 
{ 
    // This version uses a mock UrlHelper. 

    // Arrange 
    ProductsController controller = new ProductsController(repository); 
    controller.Request = new HttpRequestMessage(); 
    controller.Configuration = new HttpConfiguration(); 

    string locationUrl = "http://location/"; 

    // Create the mock and set up the Link method, which is used to create the Location header. 
    // The mock version returns a fixed string. 
    var mockUrlHelper = Isolate.Fake.Instance<UrlHelper>(); 
    Isolate.WhenCalled(() => mockUrlHelper.Link("", null)).WillReturn(locationUrl); 
    controller.Url = mockUrlHelper; 

    // Act 
    Product product = new Product() { Id = 42 }; 
    var response = controller.Post(product); 

    // Assert 
    Assert.AreEqual(locationUrl, response.Headers.Location.AbsoluteUri); 
}