我想在我的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 :(得分: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;
}
}
}