Модульное тестирование ASP.NET WebApi с Request.CreateResponse

147

Я пытаюсь написать некоторые модульные тесты для моего ApiController и столкнулся с некоторыми проблемами. Есть хороший метод расширения, называемый Request.CreateResponse, который очень помогает при генерации ответа.

public HttpResponseMessage Post(Product product)
{
  var createdProduct = repo.Add(product);
  return this.Request.CreateResponse(HttpStatusCode.Created, createdProduct);
}

Есть ли способ смоделировать CreateResponse без использования частичных имитаций или прямого использования "new HttpResponseMessage (...)"?

как
источник
1
Почему вы хотите издеваться CreateResponse? Почему бы не утверждать на возвращаемые свойства HttpResponseMessage Contentи StatusCodeсвойства, что установлены правильные значения?
nemesv
3
Если я запусту этот метод блочных тестов, произойдет сбой, за исключением того, что конфигурация не установлена.
аса
1
Хорошо, позор мне, мне просто нужно было написать это.Request.CreateResponse (HttpStatusCode.Accepted, созданный Product, GlobalConfiguration.Configuration)
asa

Ответы:

243

Другой способ решить эту проблему заключается в следующем:

controller.Request = new HttpRequestMessage();
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, 
                                  new HttpConfiguration());

Если вы обновляетесь до webapi 5.0, вам нужно изменить это на:

controller.Request = new HttpRequestMessage();
controller.Request.SetConfiguration(new HttpConfiguration());

Причина, по которой вам нужно это сделать, заключается в том, что вы должны Requestзаполнить контроллер, иначе методы расширения Requestне будут работать. У вас также должен быть HttpConfigurationустановлен запрос, иначе маршрутизация и другие части конвейера не будут работать правильно.

jonnii
источник
Да, это может сработать, но, похоже, Request.CreateResponse также работает.
ас
4
Добавление GlobalConfiguration.Configuration все еще оставило запрос пустым. Установка запроса сработала для меня, однако это не конец моих проблем, так как мое действие также вызывало Url.Link, а имя маршрута не было определено.
дурак
Помощь в настройке маршрута stackoverflow.com/questions/11779311/…
foolshat
Установка ControllerContext после этого вызова также дает мне эту ошибку, но только с WebApi 5.0.0. Но если я установить объект HttpConfiguration на запрос прошлого , он работает отлично.
Майкбридж
Это прекрасно работает, но я не понимаю, почему это работает. Не могли бы вы уточнить это в ответе?
Jan_V
24

Вы можете настроить объект контроллера для тестируемости следующим образом:

var config = new HttpConfiguration();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/products");
var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "products" } });

controller.ControllerContext = new HttpControllerContext(config, routeData, request);
controller.Request = request;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;

Скопировано из подробного поста Питера Провоста о модульном тестировании ASP.NET Web API .

mono68
источник
1
Вы также можете быть заинтересованы в документах MS, связанных с этим: docs.microsoft.com/en-us/aspnet/web-api/overview/… Вам также может понадобиться добавить ссылки на System.Web.Http и System.Net. Http
Аарон Хоффман
4

Для Web API 2 вы можете просто добавить

controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();

Вот так

[TestMethod]
public void GetReturnsProduct()
{
    // Arrange
    var controller = new ProductsController(repository);
    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();

    // Act
    var response = controller.Get(10);

    // Assert
    Product product;
    Assert.IsTrue(response.TryGetContentValue<Product>(out product));
    Assert.AreEqual(10, product.Id);
}

Важно установить запрос и конфигурацию на контроллере. В противном случае тест завершится ошибкой с ArgumentNullException или InvalidOperationException.

Смотрите здесь для получения дополнительной информации.

Дэн Фридман
источник
1

WebAPI 1 здесь с похожей проблемой, используя VB.

Мне удалось смешать ответы здесь, чтобы заставить это работать так просто:

Dim request As HttpRequestMessage = New HttpRequestMessage()
Return request.CreateResponse(HttpStatusCode.BadRequest, myCustomClassObject, GlobalConfiguration.Configuration)

Просто отправка на случай, если это кому-нибудь поможет.

Руди Скоггинс
источник
0

В вашем тестовом классе создайте экземпляр класса контроллера. напримерvar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Киран Чаудхари
источник