2016-07-14 3 views
2

나는 webapi를 배우려고 노력하고 있으며 문제를 발견했습니다. 필자가 수행 한 교육 과정에서는 다음 및 이전 링크가 포함 된 응답 헤더를 반환하여 페이징을 수행하는 방법을 보여줍니다. 그러나 HttpContext.Current.Response.Headers.Add()을 사용하여 다음 링크, 이전 링크 및 전체 페이지를 다시 보냅니다.응답 헤더가있는 단위 테스트 webapi 컨트롤러

또한 컨트롤러에 대한 단위 테스트를 구현하려고합니다. 단위 테스트를 실행할 때 HttpContext.Currentnull 인 것 같습니다. 어딘가에 내가 읽을 수없는 webappi에 대한 HttpContext.Current 안된다는 것을 읽을 수 있지만, 대신 내가 무엇을 사용해야하는지 잘 모르겠습니다.

public partial class CandidateManagerController 
{ 
    private readonly ICandidateManager _candidateManagerV2; 

    public CandidateManagerController(ICandidateManager candidateManager) 
    { 
     _candidateManagerV2 = candidateManager; 
    } 

    [VersionedRoute("CandidateManager", 2, Name="CandidateManagerV2")] 
    public IHttpActionResult Get(int page = 1, int pageSize = 1) 
    { 
     try 
     { 
      var totalCount = 0; 
      var totalPages = 0; 

      var result = _candidateManagerV2.GetCandidates(out totalCount, out totalPages, page, pageSize); 

      var urlHelper = new UrlHelper(Request); 


      var prevLink = page > 1 
       ? urlHelper.Link("CandidateManagerV2", 
        new 
        { 
         page = page - 1, 
         pageSize = pageSize, 
        }) 
       : ""; 


      var nextLink = page < totalPages ? urlHelper.Link("CandidateManagerV2", 
       new 
       { 
        page = page + 1, 
        pageSize = pageSize 
       }) : ""; 

      var paginationHeader = new 
      { 
       currentPage = page, 
       pageSize = pageSize, 
       totalCount = totalCount, 
       totalPages = totalPages, 
       previousPageLink = prevLink, 
       nextPageLink = nextLink 
      }; 

      HttpContext.Current.Response.Headers.Add("X-Pagination", Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader)); 



      return Ok(result); 
     } 
     catch (Exception exp) 
     { 
      return InternalServerError(); 
     } 
    } 

} 

가 여기 내 단위 테스트입니다 :

여기 내 콘트롤 코드입니다. 내가 Nunit과 Moq을 사용하고 있음에 유의하십시오.

[TestFixture] 
public class CandidateManagerControllerV2Tests 
{ 


    [Test] 
    [Category("CandidateManagerController Unit Tests")] 
    public void Should_Return_List_Of_Candidate_Objects() 
    { 

     var testList = new List<Candidate>(); 
     testList.Add(new Candidate() { CandidateId = 1, Name = "Mr", Surname = "Flibble" }); 
     testList.Add(new Candidate() { CandidateId = 2, Name = "Arnold", Surname = "Rimmer" }); 

     var totalCount = 0; 
     var totalPages = 0; 
     var mockManager = new Mock<ICandidateManager>(); 
     mockManager.Setup(x => x.GetCandidates(out totalCount, out totalPages, It.IsAny<int>(), It.IsAny<int>())).Returns(testList); 

     var controller = new CandidateManagerController(mockManager.Object); 
     SetupControllerForTests(controller); 

     var result = controller.Get(1, 1); 
    } 

    private static void SetupControllerForTests(ApiController controller) 
    { 
     var config = new HttpConfiguration(); 
     var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/candidatemanager"); 
     var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}"); 
     var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "products" } }); 

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

} 

누군가가 나를 도울 수 있기를 바랍니다. 페이징을 구현하는 방법으로 잘못된 길을 찾은 것일 수 있습니다. 그러나 어떤 식 으로든 응답 헤더를 추가해야 할 가능성이 큽니다.

+0

HttpContext를 조롱하지 마십시오. 대신 메모리 내 통합 테스트를 작성하십시오. 보기 : http://stephenzeng.com/Home/View/17. –

답변

0

HttpContext에 자신을 연결하지 마십시오.

헤더를 설정하고 의도대로 단위 테스트를 수행 할 수있는 또 다른 방법이 있습니다. 당신은 그것에서 ResponseMessageResult 만듭니다 HttpResponseMessage 생성 한 후 필요에 따라 헤더를 추가 :

//...code removed for brevity 

var response = Request.CreateResponse(HttpStatusCode.OK, result); 

response.Headers.Add("X-Pagination", Newtonsoft.Json.JsonConvert.SerializeObject(paginationHeader)); 

IHttpActionResult ok = ResponseMessage(response); 

return ok; 

당신은 또한 재설정하는 때문에 UrlHelper를 만들 때 컨트롤러 설정이 null 참조 오류가 발생합니다 있음을 유의 컨트롤러의 당신이 전달 된 다음 테스트는 X-Pagination 헤더를 확인하는 기본 ActionContext

private static void SetupControllerForTests(ApiController controller) { 
    var config = new HttpConfiguration(); 
    var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/candidatemanager"); 
    var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}"); 
    var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "products" } }); 

    controller.ControllerContext = new HttpControllerContext(config, routeData, request); 
    controller.Request = request; 
    controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config; 
    //commented this out as it was causing Request to be null 
    //controller.ActionContext=new HttpActionContext(); 
} 

를 할당 할 때 Request를 null로

public async Task Should_Return_Paged_List_Of_Candidate_Objects() { 
    //Arrange 
    var testList = new List<Candidate>(); 
    testList.Add(new Candidate() { CandidateId = 1, Name = "Mr", Surname = "Flibble" }); 
    testList.Add(new Candidate() { CandidateId = 2, Name = "Arnold", Surname = "Rimmer" }); 

    var totalCount = 0; 
    var totalPages = 0; 
    var mockManager = new Mock<ICandidateManager>(); 
    mockManager.Setup(x => x.GetCandidates(out totalCount, out totalPages, It.IsAny<int>(), It.IsAny<int>())).Returns(testList); 

    var controller = new CandidateManagerController(mockManager.Object); 
    SetupControllerForTests(controller); 

    //Act 
    var response = await controller.Get(1, 1).ExecuteAsync(System.Threading.CancellationToken.None); 

    //Assert 
    Assert.IsNotNull(response); 
    Assert.IsInstanceOfType(response, typeof(HttpResponseMessage)); 
    Assert.IsTrue(response.Headers.Contains("X-Pagination")); 
} 
+0

요청에 스트림이있는 경우 어떻게 테스트 할 수 있습니까? 멀티 파트 컨텍스트에서. 이렇게 테스트하고 싶습니다만, HttpServer 메모리를 사용하여 끝났습니다. 요청은 실제 상황처럼 처리됩니다. – ntohl

+0

@ntohl은 테스트중인 시스템을 실행하는 데 필요한 것을 요청으로 채 웁니다. 요청의 Content 속성을 그에 맞게 설정하십시오. – Nkosi

+0

나는 그것을 관리했다. 감사. 그러나 CORS를 평등에 추가 한 후에 헤더가'[EnableCors ("*", "Origin", "POST")]에서 올바르게 생성되었는지 확인해야하고, 또한 커스텀 MessageHandler 응답에했다. – ntohl