模拟业务层以进行Web API的集成测试

时间:2014-01-13 20:03:29

标签: asp.net-web-api mocking integration-testing

我想在我的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);
    }

1 个答案:

答案 0 :(得分: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;
        }
    }
}