2017-08-16 113 views
1

我一直在閱讀文檔,對於如何實現這一點我有點困惑。我有一個名爲NewsController的WebAPI控制器,我將在下面列出。它有一個構造函數,目前需要三個依賴項。我爲DryIoc創建了一個靜態類,因此我可以在整個項目中全局使用它,並在啓動時進行初始化。如何使用DryIoc解決WebAPI控制器的依賴關係

我想要做的就是將控制器及其依賴關係註冊到我的DryIoc類中,然後以某種方式在NewsController控制器中解決該問題。我想這樣做的原因是,當我開始測試時,我可以簡單地讓測試項目更改註冊控制器的範圍,並使用存根或模擬實現。

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(它的一部分反正)

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:

到目前爲止,我有 「自動」 依賴分辨率經歷WebApiConfig但是我我不確定如何從測試項目訪問這個,所以我可以用我的存根替換真正的實現。

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

回答

1

好吧,他重新是我想出的。

在上面的問題更新:你會看到代碼將自動註冊和解決使用WebAPIConfig的依賴關係。你需要使用NuGet的DryIoc.WebAPI包以及DryIoc。

爲了能夠替換測試實現,您需要爲測試/模擬依賴關係創建一個類。您可以僅使用RegisterDependencies以上,但註冊您的存根或模擬而不是生產實現。

那麼你的測試類(我用的xUnit)將是這個樣子,雖然不用擔心在構造函數中AutoMapper部分:

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

     } 


    } 
}