2014-12-22 4 views
1

Я использую версию MVC 4 Anthony Steele's MVC Route Tester, которая, как представляется, является лучшим предложением для тестирования маршрутов MVC.Тестирование маршрутов API API с помощью MvcRouteTester

Я пытаюсь получить следующий тест веб-API для работы, но этого не происходит. Может кто-то помочь мне:

var config = new HttpConfiguration(); 

config.Routes.MapHttpRoute(
    name: "Testing", 
    routeTemplate: "WebServices/Test.aspx", 
    defaults: new 
    { 
     controller = "Test" // This maps to an ApiController called TestController 
    } 
); 

config 
    .ShouldMap("/WebServices/Test.aspx") 
    .To<TestController>(HttpMethod.Get, x => x.Get()); 

Этот тест завершается с ошибкой MvcRouteTester.Assertions.AssertionException: Маршрут с контроллером не найден для URL-адрес HTTP: // site.com/WebServices/Test.aspx.

Маршрут работает, когда я фактически запускаю сайт, просто не в моем тестовом проекте. Что может быть неправильным?

ответ

1

Я выяснил проблему после того, как выкопал код. Внутри стека есть вызов, чтобы получить «экспортируемые типы» из сборки моего веб-сайта. В производстве вызов преуспевает, но поскольку в моем модульном тестовом проекте отсутствует пара ссылок на сборки, вызов Assembly.GetExportableTypes() выдает исключение. Это исключение поймано и отбрасывается, поэтому было очень сложно отладить причину, по которой я позже получал исключение «контроллер не найден».

Можно устранить проблему, убедившись, что вы добавили все необходимые сборки. Но если вы хотите сделать жизнь проще для себя, вы можете фактически заменить службу IHttpControllerTypeResolver, которая подавляет исключение. Ниже приведен пример повторной реализации IHttpControllerTypeResolver.

public class HttpControllerTypeResolverThatDoesNotIgnoreExceptionGettingLoadableTypes : DefaultHttpControllerTypeResolver 
{ 
    public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) 
    { 
     if (assembliesResolver == null) 
     { 
      throw new Exception(); 
     } 

     var result = new List<Type>(); 

     // Go through all assemblies referenced by the application and search for types matching a predicate 
     ICollection<Assembly> assemblies = assembliesResolver.GetAssemblies(); 
     foreach (Assembly assembly in assemblies) 
     { 
      Type[] exportedTypes = null; 
      if (assembly == null || assembly.IsDynamic) 
      { 
       // can't call GetExportedTypes on a dynamic assembly 
       continue; 
      } 

      try 
      { 
       exportedTypes = assembly.GetExportedTypes(); 
      } 
      catch (ReflectionTypeLoadException ex) 
      { 
       exportedTypes = ex.Types; 
       Trace.TraceError(ex.ToString()); 
      } 
      catch (Exception ex) 
      { 
       Trace.TraceError(ex.ToString()); 
       continue; 
      } 

      if (exportedTypes != null) 
      { 
       result.AddRange(exportedTypes.Where(IsControllerType)); 
      } 
     } 

     return result; 
    } 

    private static bool IsControllerType(Type t) 
    { 
     return 
      t != null && 
      t.IsClass && 
      t.IsPublic && 
      t.Name.EndsWith(DefaultHttpControllerSelector.ControllerSuffix, StringComparison.OrdinalIgnoreCase) && 
      !t.IsAbstract && 
      typeof(IHttpController).IsAssignableFrom(t); 
    } 
} 

Вы можете Подвод этой услуги в вашу конфигурацию, как это:

_yourHttpConfig.Services.Replace(typeof(IHttpControllerTypeResolver), new HttpControllerTypeResolverThatDoesNotIgnoreExceptionGettingLoadableTypes()); 

выше реализация будет выводить какое-либо исключение, возникающее в след, который может помочь при отладке. В качестве альтернативы вы можете использовать такой метод, как this one, чтобы пропустить любой из отдельных экспортируемых типов, которые не могли быть успешно загружены, но все равно получить остальную часть успешных экспортируемых типов.

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