Есть ли пример кода, который показывает модульное тестирование контроллера, который наследуется от контроллера api? Я пытаюсь выполнить unit test POST, но он не работает. Я считаю, что мне нужно настроить HttpControllerContext для тестирования, но не знаю, как Благодаря
Пример кода для тестирования модулей api-контроллеров
Ответ 1
этот код должен продемонстрировать основы пост-теста. Предполагается, что у вас есть репозиторий, введенный в контроллер. Я использую MVC 4 RC not Beta здесь, если вы используете Beta Request.CreateResponse(... немного отличается, так что дайте мне крик...
Данный код контроллера немного похож на это:
public class FooController : ApiController
{
private IRepository<Foo> _fooRepository;
public FooController(IRepository<Foo> fooRepository)
{
_fooRepository = fooRepository;
}
public HttpResponseMessage Post(Foo value)
{
HttpResponseMessage response;
Foo returnValue = _fooRepository.Save(value);
response = Request.CreateResponse<Foo>(HttpStatusCode.Created, returnValue, this.Configuration);
response.Headers.Location = "http://server.com/foos/1";
return response;
}
}
unit test будет выглядеть примерно так (NUnit и RhinoMock)
Foo dto = new Foo() {
Id = -1,
Name = "Hiya"
};
IRepository<Foo> fooRepository = MockRepository.GenerateMock<IRepository<Foo>>();
fooRepository.Stub(x => x.Save(dto)).Return(new Foo() { Id = 1, Name = "Hiya" });
FooController controller = new FooController(fooRepository);
controller.Request = new HttpRequestMessage(HttpMethod.Post, "http://server.com/foos");
//The line below was needed in WebApi RC as null config caused an issue after upgrade from Beta
controller.Configuration = new System.Web.Http.HttpConfiguration(new System.Web.Http.HttpRouteCollection());
var result = controller.Post(dto);
Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Expecting a 201 Message");
var resultFoo = result.Content.ReadAsAsync<Foo>().Result;
Assert.IsNotNull(resultFoo, "Response was empty!");
Assert.AreEqual(1, resultFoo.Id, "Foo id should be set");
Ответ 2
Используя AutoFixture, я обычно делаю что-то вроде этого:
[Theory, AutoCatalogData]
public void PostToCollectionReturnsCorrectResponse(
CategoriesController sut,
CategoryRendition categoryRendition)
{
HttpResponseMessage response = sut.Post(categoryRendition);
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
}
Подробнее об этом подходе см. этот другой ответ SO.
Ответ 3
Я создал общее решение для вызова некоторых действий и получения HttpResponseMessage в качестве словаря, который очень удобен для использования.
Первое расширение для словаря:
public static class DictionaryExtensions
{
public static void AddRange<T, S>(this Dictionary<T, S> source,
Dictionary<T, S> collection)
{
if (collection == null)
{
throw new NullReferenceException("Collection is null");
}
foreach (var item in collection)
{
source.Add(item.Key, item.Value);
}
}
}
Теперь запросите создание части:
public class RequestCreator
{
protected static void FirstPart(ApiController controller,
HttpMethod method,String actionUrl)
{
// Creating basic request message with message type and requesting
// url example : 'http://www.someHostName/UrlPath/'
controller.Request = new HttpRequestMessage(method, actionUrl);
// Adding configuration for request
controller.Request.Properties.
Add(HttpPropertyKeys.HttpConfigurationKey,new HttpConfiguration());
}
protected static Dictionary<String, Object> SecondPart
(HttpResponseMessage response)
{
// Adding basic response content to dictionary
var resultCollection = new Dictionary<String, Object>
{
{"StatusCode",response.StatusCode},
{"Headers",response.Headers},
{"Version",response.Version},
{"RequestMessage",response.RequestMessage},
{"ReasonPhrase",response.ReasonPhrase},
{"IsSuccessStatusCode",response.IsSuccessStatusCode}
};
var responseContent = response.Content;
// If response has content then parsing it and
// getting content properties
if (null != responseContent)
{
var resultMessageString = response.Content.
ReadAsStringAsync().Result;
resultCollection.AddRange((new JavaScriptSerializer()).
DeserializeObject(resultMessageString)
as Dictionary<String, Object>);
}
return resultCollection;
}
}
И, наконец, ответное сообщение в класс конвертера слова:
public class HttpResponseModelGetter : RequestCreator
{
public Dictionary<String, Object>
GetActionResponse(ApiController controller,HttpMethod method,
String actionUrl,Func<HttpResponseMessage> callBack)
{
FirstPart(controller, method, actionUrl);
var response = callBack();
return SecondPart(response);
}
}
public class HttpResponseModelGetter<T> : RequestCreator
{
public Dictionary<String, Object>
GetActionResponse(ApiController controller,HttpMethod method,
String actionUrl,Func<T,HttpResponseMessage> callBack,T param)
{
FirstPart(controller, method, actionUrl);
var response = callBack(param);
return SecondPart(response);
}
}
public class HttpResponseModelGetter<T1,T2> : RequestCreator
{
public Dictionary<String, Object>
GetActionResponse(ApiController controller,HttpMethod method,
String actionUrl,Func<T1,T2,HttpResponseMessage> callBack,
T1 param1,T2 param2)
{
FirstPart(controller, method, actionUrl);
var response = callBack(param1,param2);
return SecondPart(response);
}
}
//and so on...
и использование:
var responseGetter = new HttpResponseModelGetter();
var result = responseGetter.GetActionResponse(controller,HttpMethod.Get,
"http://localhost/Project/api/MyControllerApi/SomeApiMethod",
controller.SomeApiMethod);
Boolean isComplete = Boolean.Parse(result["isComplete"].ToString());
Ответ 4
Пример кода для модуля тестирования API-контроллера с асинхронным финансированием в С#
-
Подготовить тестовые модели:
using System; namespace TestAPI.Models { public class TestResult { public DateTime Date { get; set; } public bool Success { get; set; } public string Message { get; set; } } }
-
Подготовьте тестовый контроллер
using TestAPI.Models; using System; using System.Net; using System.Threading.Tasks; using System.Web.Http; using System.Web.Http.Description; namespace TestAPI.Controllers { public class TestController : ApiController { public TestController() { } [HttpPost] [ResponseType(typeof(TestResult))] [Route("api/test/start")] public async Task<IHttpActionResult> StartTest() { DateTime startTime = DateTime.Now; var testProcessor = new TestAsync(); await testProcessor.StartTestAsync(); HttpStatusCode statusCode = HttpStatusCode.OK; return Content(statusCode, new TestResult { Date = DateTime.Now, Success = true, Message = "test" }); } } }
-
unit test асинхронный контроллер с проверкой результата от ответа
using Microsoft.VisualStudio.TestTools.UnitTesting; using TestAPI.Controllers; using TestAPI.Models; using System.Web.Http; using System.Threading.Tasks; using System.Net; using System.Web.Script.Serialization; namespace Unit.Tests.Controllers { /// <summary> /// Summary description for ControllerTest /// </summary> [TestClass] public class ControllerTest { private TestController _testController; [TestInitialize] public void estAPI_Initializer() { _testController = new TestController(); var configuration = new HttpConfiguration(); System.Net.Http.HttpRequestMessage request = new System.Net.Http.HttpRequestMessage(); request.Headers.Add("Authorization", "Bearer 1232141241"); request.Headers.Add("ContentType", "application/json"); _testController.Request = request; _testController.Configuration = configuration; } [TestCategory("Unit test")] [TestMethod] public async Task API_Async_Controller_Test() { IHttpActionResult asyncResponse = await _testController.StartTest(); var cToken = new System.Threading.CancellationToken(true); var rResult = asyncResponse.ExecuteAsync(cToken); Assert.IsNotNull(rResult); Assert.IsNotNull(rResult.Result); Assert.AreEqual(rResult.Result.StatusCode, HttpStatusCode.OK); Assert.IsNotNull(rResult.Result.Content); var rContent = rResult.Result.Content; string data = await rContent.ReadAsStringAsync(); Assert.IsNotNull(data); JavaScriptSerializer JSserializer = new JavaScriptSerializer(); var finalResult = JSserializer.Deserialize<TestResult>(data); Assert.IsNotNull(finalResult); Assert.IsTrue(finalResult.Success); } } }