2014-01-13 30 views
4

我想在Web API上执行集成测试,而不依赖于业务层接口。模拟用于集成测试Web API的业务层

当这个动作被执行:

1)我想嘲笑_Service对象并确认被称为

2)我想断言,返回正确的StatusCode

编号2是没有问题的,但是当我不控制/手动开始创建api控制器时,如何模拟_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

您是否部署到特定集成测试环境?您可以简单地在您的Web.Config中添加一个关键字,该关键字在特定的测试环境中表示IntegrationTesting = true,并且在您定义“ISchoolyearService”的注入时在真正的实现或您在IntegrationTesting == true时创建的模拟服务之间切换。 – Karhgath

+0

“部署到特定的集成测试环境”?你会说测试自我托管与iis托管吗?我正在使用HttpServer和HttpClient进行集成测试。但无论如何,我不明白你的建议如何能帮助我。 – Elisabeth

+1

那么,您使用什么IoC将真正的服务注入ISchoolyearService?根据Web.Config中的键,您可以在模拟对象或实际服务之间切换。如果你的问题是关于如何创建模拟对象,你可以通过手工或使用许多模拟框架来完成,例如Moq: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; 
     } 
    } 
} 
相关问题