2014-01-13 1 views
4

비즈니스 계층 인터페이스에 의존하지 않고 내 웹 API에서 통합 테스트를 수행하고 싶습니다. 이 작업이 실행웹 API 통합 테스트를위한 비즈니스 계층 모의

:

1) 내가 올바른 상태 코드가 반환되는 것을 주장 할)을 _service 개체를 조롱 그냥

2

라고되어 있는지 확인하려면

번호 2는 아무런 문제가 없지만 APC 컨트롤러를 수동으로 만들거나 제어하지 않으면 _service 개체 (ISchoolyearService)를 조롱 할 수 있습니다. 이는 컨트롤러 테스트에서 수행되는 작업이기 때문입니다. 하지만 내 API를 단위 테스트하고 싶지 않아!

[RoutePrefix("api/schoolyears")] 
    public class SchoolyearController : ApiController 
    { 
     private readonly ISchoolyearService _service; 
     public SchoolyearController(ISchoolyearService service) 
     { 
      _service = service; 
     } 



[Route("")] 
    [HttpPost] 
    public HttpResponseMessage Post([FromBody]SchoolyearCreateRequest request) 
    { 
     _service.CreateSchoolyear(request); 
     return Request.CreateResponse(HttpStatusCode.Created); 
    } 
+0

특정 통합 테스트 환경에 배포합니까? 특정 테스트 env에 IntegrationTesting = true를 지정하고 IntegrationTesting == true 일 때 작성한 실제 구현 또는 모의 서비스간에 전환하는 'ISchoolyearService'에 대한 주입을 정의 할 때 Web.Config에 키를 간단히 추가 할 수 있습니다. – Karhgath

+0

"특정 통합 테스트 환경에 배포"? 요 호스트 호스팅 테스트 대 자기 호스팅 말합니까? 나는 HttpServer와 HttpClient를 사용하여 통합 테스트를하고있다. 그러나 어쨌든 나는 그것이 나를 도울 수있는 당신의 제안을 이해하지 못한다. – Elisabeth

+1

글쎄, 실제 서비스를 ISchoolyearService에 주입하는 데 IoC를 사용합니까? Web.Config의 키에 따라 모의 객체 또는 실제 서비스간에 전환 할 수 있습니다. 모의 객체를 만드는 방법에 관한 문제인 경우 Mook : http://www.nuget.org/packages/MOQ와 같이 손으로 또는 많은 조롱 프레임 워크를 사용하여 수행 할 수 있습니다. 어쩌면 당신은 당신의 문제에 대해 구체적으로 가르쳐 줄 수 있을까요? – Karhgath

답변

4

다음은 메모리 내 통합 테스트를 수행하는 방법에 대한 기본적인 예입니다. 여기에서는 Unity.WebApi.UnityDependencyResolver을 사용하여 모의 의존성을 주입합니다. 비슷한 다른 IoC 컨테이너를 사용할 수 있습니다.

using Microsoft.Practices.Unity; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Net; 
using System.Net.Http; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Web.Http; 
using Unity.WebApi; 

namespace WebApplication251.Tests.Controllers 
{ 
    [TestClass] 
    public class PeopleControllerTest 
    { 
     string baseAddress = "http://dummyhost/"; 

     [TestMethod] 
     public void PostTest() 
     { 
      HttpConfiguration config = new HttpConfiguration(); 

      // use the configuration that the web application has defined 
      WebApiConfig.Register(config); 

      //override the dependencies with mock ones 
      RegisterMockDependencies(config); 

      HttpServer server = new HttpServer(config); 

      //create a client with a handler which makes sure to exercise the formatters 
      HttpClient client = new HttpClient(new InMemoryHttpContentSerializationHandler(server)); 

      SchoolyearCreateRequest req = new SchoolyearCreateRequest(); 

      using (HttpResponseMessage response = client.PostAsJsonAsync<SchoolyearCreateRequest>(baseAddress + "api/schoolyears", req).Result) 
      { 
       Assert.IsNotNull(response.Content); 
       Assert.IsNotNull(response.Content.Headers.ContentType); 
       Assert.AreEqual<string>("application/json; charset=utf-8", response.Content.Headers.ContentType.ToString()); 

       SchoolyearCreateRequest recSCR = response.Content.ReadAsAsync<SchoolyearCreateRequest>().Result; 

       //todo: verify data 
      } 
     } 

     private void RegisterMockDependencies(HttpConfiguration config) 
     { 
      var unity = new UnityContainer(); 

      unity.RegisterType<ISchoolyearService, MockSchoolyearService>(); 

      config.DependencyResolver = new UnityDependencyResolver(unity); 
     } 
    } 

    [RoutePrefix("api/schoolyears")] 
    public class SchoolyearController : ApiController 
    { 
     private readonly ISchoolyearService _service; 
     public SchoolyearController(ISchoolyearService service) 
     { 
      _service = service; 
     } 

     [Route] 
     [HttpPost] 
     public HttpResponseMessage Post([FromBody]SchoolyearCreateRequest request) 
     { 
      _service.CreateSchoolyear(request); 
      return Request.CreateResponse(HttpStatusCode.Created); 
     } 
    } 

    public class InMemoryHttpContentSerializationHandler : DelegatingHandler 
    { 
     public InMemoryHttpContentSerializationHandler(HttpMessageHandler innerHandler) 
      : base(innerHandler) 
     { 
     } 

     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     { 
      request.Content = await ConvertToStreamContentAsync(request.Content); 

      HttpResponseMessage response = await base.SendAsync(request, cancellationToken); 

      response.Content = await ConvertToStreamContentAsync(response.Content); 

      return response; 
     } 

     private async Task<StreamContent> ConvertToStreamContentAsync(HttpContent originalContent) 
     { 
      if (originalContent == null) 
      { 
       return null; 
      } 

      StreamContent streamContent = originalContent as StreamContent; 

      if (streamContent != null) 
      { 
       return streamContent; 
      } 

      MemoryStream ms = new MemoryStream(); 

      await originalContent.CopyToAsync(ms); 

      // Reset the stream position back to 0 as in the previous CopyToAsync() call, 
      // a formatter for example, could have made the position to be at the end 
      ms.Position = 0; 

      streamContent = new StreamContent(ms); 

      // copy headers from the original content 
      foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers) 
      { 
       streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value); 
      } 

      return streamContent; 
     } 
    } 
} 
관련 문제