1

Ich habe die Dokumentation gelesen und bin ein wenig verwirrt, wie ich das erreichen würde. Ich habe einen WebAPI-Controller namens NewsController, den ich unten auflisten werde. Es hat einen einzelnen Konstruktor, der derzeit drei Abhängigkeiten benötigt. Ich habe eine statische Klasse für DryIoc erstellt, damit ich sie während des gesamten Projekts global verwenden kann. Sie wird beim Start initialisiert.So lösen Sie die Abhängigkeiten eines WebAPI-Controllers mit DryIoc

Was ich tun möchte, ist den Controller mit seinen Abhängigkeiten in meiner DryIoc-Klasse registrieren und dann das im NewsController-Controller irgendwie auflösen. Der Grund, warum ich das machen möchte, ist, dass ich beim Testen einfach den Umfang des registrierten Controllers ändern und die stubbed oder mocked Implementierungen verwenden kann.

RegisterDependencies

public static class RegisterDependencies 
    { 
     public static Container container; 

    public static void Initialize() 
    { 
     container = new Container(rules => rules 
     .WithDefaultReuseInsteadOfTransient(Reuse.InWebRequest) 
     .WithoutThrowOnRegisteringDisposableTransient() 
     .WithoutImplicitCheckForReuseMatchingScope()); 

     container.Register<INewsManager, NewsManager>(); 
     container.Register<IGetNews, NewsManager>(); 
     container.Register<IAddNews, NewsManager>(); 

     container.Register<ILoggingService, Logger>(); 

     container.Register<NewsController>(made: Made.Of(() => new NewsController 
      (Arg.Of<ILoggingService>(), Arg.Of<IGetNews>(), Arg.Of<IAddNews>(), 
      Arg.Of<INewsManager>()))); 
    } 
} 

Newscontroller (ein Teil davon sowieso)

public class NewsController : ApiController 
    { 
     private INewsManager _nm; 
     private IGetNews _getNews; 
     private IAddNews _addNews; 
     private ILoggingService _log; 

    public NewsController(ILoggingService logger, IGetNews getNews, 
     IAddNews addNews, INewsManager newsManager) 
    { 
     _getNews = getNews; 
     _addNews = addNews; 
     _log = logger; 
     _nm = newsManager; 
    } 

    [HttpGet] 
    public IHttpActionResult GetNews() 
    { 

     var newsItems = _getNews.GetNews(); 

     if (newsItems == null || newsItems.Count() <= 0) 
     { 
      _log.Error("News Items couldn't be loaded."); 

      return NotFound(); 
     } 



     return Ok(Mapper.Map<List<NewsDto>>(newsItems)); 
    } 

UPDATE:

Bisher habe ich "automatisch" Abhängigkeitsauflösung gehen durch WebApiConfig haben aber ich bin mir nicht sicher, wie ich vom Testprojekt darauf zugreifen kann, damit ich die realen Implementierungen mit meinen Stubs austauschen kann.

WebApiConfig

public static void Register(HttpConfiguration config) 
     { 
     // Web API configuration and services 
     config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 

     // Web API routes 
     config.MapHttpAttributeRoutes(); 

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

     RegisterDependencies.controllerContainer = new Container(rules => rules.With(FactoryMethod.ConstructorWithResolvableArguments)).WithWebApi(
      config, throwIfUnresolved: type => type.IsController()); 
     RegisterDependencies.InitializeControllerContainer(RegisterDependencies.controllerContainer); 

     } 

RegisterDependencies

public static class RegisterDependencies 
    { 
     public static IContainer controllerContainer; 

     public static void InitializeControllerContainer(IContainer ControllerContainer) 
     { 

      ControllerContainer.RegisterMany<ILoggingService, Logger>(setup: Setup.With(allowDisposableTransient: true)); 
      ControllerContainer.RegisterMany<INews, NewsManager>(setup: Setup.With(allowDisposableTransient: true)); 
     } 

Newscontroller

public class NewsController : ApiController 
    { 
     private INews _news; 
     private ILoggingService _log; 

     public NewsController(INews news, ILoggingService logger) 
     { 
      _news = news; 
      _log = logger; 
     } 

Antwort

1

Okay er Re ist, was ich mir ausgedacht habe.

In der obigen Frage unter UPDATE: sehen Sie den Code, der automatisch Abhängigkeiten mit WebAPIConfig registrieren und auflösen wird. Sie müssen das DryIoc.WebAPI-Paket von NuGet sowie DryIoc verwenden.

Um Testimplementierungen austauschen zu können, sollten Sie eine Klasse für Ihre Test-/Mock-Abhängigkeiten erstellen. Sie können einfach RegisterDependencies oben verwenden, aber registrieren Sie Ihre Stubs oder Mocks anstelle der Produktionsimplementierungen.

dann Ihre Testklasse (ich verwende xUnit) wird so etwas wie dieses, obwohl schauen Sie sich keine Sorgen um den AutoMapper Abschnitt im Konstruktor:

public class NewsControllerTests 
    { 
     private IContainer _testContainer; 
     private NewsController _controller; 

     public NewsControllerTests() 
     { 
      Mapper.Initialize(config => 
      { 
       config.CreateMap<News, NewsDto>(); 
       config.CreateMap<NewsDto, News>(); 
      }); 

      _testContainer = RegisterTestDependencies.testContainer = new Container(rules => rules.With(FactoryMethod.ConstructorWithResolvableArguments)).WithWebApi(
       new HttpConfiguration(), throwIfUnresolved: type => type.IsController()); 

      RegisterTestDependencies.InitializeTestContainer(_testContainer); 

     } 

     [Fact] 
     void GetNews_WithoutId_ReturnsAllNewsItems() 
     { 
      //Arrange 

     using (var scope = _testContainer.OpenScope(Reuse.WebRequestScopeName)) 
     { 
      _controller = scope.Resolve<NewsController>(); 

      //Act 

      var getNewsResult = _controller.GetNews() as OkNegotiatedContentResult<List<NewsDto>>; 

      //Assert 

      getNewsResult.Content.Should().AllBeOfType<NewsDto>(); 

     } 


    } 
} 
Verwandte Themen