2012-05-22 2 views
5

Я получаю «внутреннюю ошибку сервера» (код состояния 500) при тестировании контроллера веб-API ASP.NET в in-memory test.Внутренняя ошибка сервера в тесте ASP.NET Web API in-memory

[TestFixture] 
public class ValuesControllerTest 
{ 
    private HttpResponseMessage response; 

    [TestFixtureSetUp] 
    public void Given() 
    { 
     var config = new HttpConfiguration 
     { 
      IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always 
     }; 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { controller = typeof(ValuesController).Name.Replace("Controller", string.Empty), id = RouteParameter.Optional } 
     ); 

     //This method will cause internal server error but NOT throw any exceptions 
     //Remove this call and the test will be green 
     ScanAssemblies(); 

     var server = new HttpServer(config); 
     var client = new HttpClient(server); 
     response = client.GetAsync("http://something/api/values/5").Result; 
     //Here response has status code 500 

    } 

    private void ScanAssemblies() 
    { 
     PluginScanner.Scan(".\\", IsApiController); 
    } 

    private bool IsApiController(Type type) 
    { 
     return typeof (ApiController).IsAssignableFrom(type); 
    } 

    [Test] 
    public void Can_GET_api_values_5() 
    { 
     Assert.IsTrue(response.IsSuccessStatusCode); 
    } 
} 

public static class PluginScanner 
{ 
    public static IEnumerable<Type> Scan(string directoryToScan, Func<Type, bool> filter) 
    { 
     var result = new List<Type>(); 
     var dir = new DirectoryInfo(directoryToScan); 

     if (!dir.Exists) return result; 

     foreach (var file in dir.EnumerateFiles("*.dll")) 
     { 
      result.AddRange(from type in Assembly.LoadFile(file.FullName).GetTypes() 
          where filter(type) 
          select type); 
     } 
     return result; 
    } 
} 

Я сконфигурировал Visual Studio для разрыва при получении какого-либо исключения .Net. Код не останавливается ни при каких обстоятельствах, и я не могу найти какие-либо детали исключения в ответе.

Что делать, чтобы узнать, что вызывает «внутреннюю ошибку сервера»?

+0

Какова трассировка стека? Поместите это здесь. – Aliostad

+0

Ну, в этом проблема. Я не получаю трассировку стека. Только ответ «Внутренняя ошибка сервера» –

+0

означает, что означает '// дополнительная конфигурация'? Вы опустили какой-то код? – Aliostad

ответ

9

Исключение составляет в Response.Content

if (Response != null && Response.IsSuccessStatusCode == false) 
{ 
    var result = Response.Content.ReadAsStringAsync().Result; 
    Console.Out.WriteLine("Http operation unsuccessfull"); 
    Console.Out.WriteLine(string.Format("Status: '{0}'", Response.StatusCode)); 
    Console.Out.WriteLine(string.Format("Reason: '{0}'", Response.ReasonPhrase)); 
    Console.Out.WriteLine(result); 
} 
+1

Как было предложено в другом ответе, вам может потребоваться установить политику подробных ошибок var config = new HttpConfiguration {IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always}; –

4

Вам нужно добавить маршрут, так что это выглядит примерно так:

 var config = new HttpConfiguration() 
     { 
      IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always 
     }; 

     config.Routes.MapHttpRoute(
      name: "default", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { controller = "Home", id = RouteParameter.Optional }); 

     var server = new HttpServer(config); 
     var client = new HttpClient(server); 

     HttpResponseMessage response = client.GetAsync("http://somedomain/api/product").Result; 

Btw, в последних битах вы получаете 404 Not Found, как можно было бы ожидать.

Хенрик

+0

У меня есть все уже. На самом деле, у меня довольно много конфигураций. Маршруты, фильтры, контейнер IoC и т. Д. Моя проблема заключается в том, что что-то происходит в конвейере, в результате чего внутренняя ошибка отправляется обратно, но нет информации об этом. –

+0

@ Мартин Нильссон - Хенрик - архитектор WebAPI. Я бы послушал его. – RickAndMSFT

0

Это звучит, как вы, возможно, уже нашли ответ на свой вопрос, но это не совсем это для меня, поэтому я хочу, чтобы добавить это для другие с моей проблемой.

Для начала, похоже, проблема связана с новыми форматировщиками MVC 4. Установка любого из флагов политики ошибок не будет работать (IncludeErrorDetailPolicy, CustomErrors и т. Д.), Эти форматирующие элементы игнорируют их и просто возвращают и пустуют «внутреннюю ошибку сервера» 500.

Я обнаружил это, в конечном итоге перегружая форматы и проверяя их ответы на ошибки:

public class XmlMediaTypeFormatterWrapper : XmlMediaTypeFormatter 
{ 
    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext) 
    { 
     var ret = base.WriteToStreamAsync(type, value, stream, contentHeaders, transportContext); 
     if (null != ret.Exception) 
      // This means there was an error and ret.Exception has all the error message data you would expect, but once you return below, all you get is a blank 500 error... 

     return ret; 
    } 
} 

Сейчас я использую Xml и JSon FORMATTER оберток, которые просто искать ret.Exception и захватить его, так что я по крайней мере, есть данные, если 500 происходит. Я действительно не мог найти элегантный способ сделать ошибку на самом деле отображаться в html-ответе, поскольку Task.Exception уже установлен, и это СЛЕДУЕТ быть всем, что необходимо для передачи исключения.

Смежные вопросы