1

J'ai lu la documentation et je suis un peu confus quant à la façon dont j'y arriverais. J'ai un contrôleur WebAPI appelé NewsController que je liste ci-dessous. Il a un seul constructeur qui prend actuellement trois dépendances. J'ai créé une classe statique pour DryIoc afin que je puisse l'utiliser globalement dans le projet et qu'il soit initialisé au démarrage. Ce que je voudrais faire est d'enregistrer le contrôleur avec ses dépendances dans ma classe DryIoc puis de résoudre cela dans le contrôleur NewsController. La raison pour laquelle je veux faire cela est que lorsque je commence à tester, je peux simplement faire en sorte que le projet de test change la portée du contrôleur enregistré et utilise les implémentations stubbed ou mockées.Comment résoudre les dépendances d'un contrôleur WebAPI avec DryIoc

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 (partie de toute façon)

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)); 
    } 

MISE À JOUR:

Jusqu'à présent, j'avoir une résolution dépendance "automatique" en passant par WebApiConfig mais je Je ne sais pas comment y accéder à partir du projet de test afin que je puisse échanger les implémentations réelles avec mes talons.

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; 
     } 

Répondre

1

Bien qu'il re est ce que je suis venu avec.

Dans la question ci-dessus sous MISE À JOUR: vous verrez le code qui enregistrera automatiquement et résoudre les dépendances en utilisant WebAPIConfig. Vous aurez besoin d'utiliser le paquet DryIoc.WebAPI de NuGet ainsi que DryIoc. Pour pouvoir échanger des implémentations de test, vous devez créer une classe pour vos dépendances de test/simulation. Vous pouvez simplement utiliser RegisterDependencies ci-dessus mais enregistrez vos stubs ou mocks au lieu des implémentations de production.

Ensuite, votre classe de test (j'utilise xUnit) ressemblera à quelque chose comme ça mais ne vous inquiétez pas de la section AutoMapper dans le constructeur:

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>(); 

     } 


    } 
}