Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Dependency Injection in .NET applications

599 views

Published on

An overview of dependency injection for .NET applications with a strategy for updating brownfield application to adapt to IoC.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Dependency Injection in .NET applications

  1. 1. Dependency Injection with .NET -OR- So you’ve decided to finally inject your dependencies -OR- Let’s test production scenarios so it doesn’t break
  2. 2. Overview • What is DI? • Why use DI? • Where to use DI? • How to do DI? • C#, Legacy Code, and DI – Interfaces, and Singletons, and Mocks, oh my!
  3. 3. What is Dependency Injection • A software design pattern that implements inversion of control for resolving dependencies. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. – Wikipedia AppIoC Dependency Concrete Implementation Concrete Implementation Concrete Implementation
  4. 4. Dependency Inject – An Example • Legacy code w/o DI public class ReviewManager{ public ElasticSearchBackedReviewRepository ReviewsRepo {get; set;} public void GetReviewsByMovie( int movieId){ return ElasticSearchBackedReviewRepository.GetReviews(movieId); } } • Legacy code w/o DI public class ReviewManager{ public IReviewRepository ReviewsRepo {get; set;} Public ReviewManager( IReviewRepository repo ){ ReviewsRepo = repo; } public void GetReviewsByMovie( int movieId){ return ReviewsRepo.GetReviews(moviedId); } } AppIoC Dependency Concrete Implementation Concrete Implementation Concrete Implementation
  5. 5. Why Interfaces? • Develop against a contract – Business logic isn’t changed as new implementations are introduced • Moq (for unit tests) requires interfaces or virtual methods. • All wiring for dependencies can be performed in a centralized location
  6. 6. Why Mocking? • Allows testing any use case without the need for test data – Mock a response that returns the use case you are testing (as opposed to test data in the DB) – Null return values – Timeout (web service clients) – 0 reviews, 1 review, 10000 reviews
  7. 7. When? Architecture Boundaries App (Front End) App (Business Logic) DB 1 DB 2 Service 1 Service 1 Service 1 Any time the app reaches out for data is a good candidate for dependency injection. In this scenario, the clients we use to wrap the 2 databases and the 3 services would each implement an interface that could be mocked for unit tests
  8. 8. When? Responsibility Boundaries • Fandango Desktop/Mobile Web – Reviews (Direct DB calls, Elastic search service) – Movies (DB calls, movie service) – Theaters (DB calls, Commerce service, old service, new API)
  9. 9. DI via Delegates • Initial Effort is low – No extra frameworks – unit test can define the mocked method • Subsequent efforts are O(N) – One change per new mocked method • Pros – Methods can be incorporated one at a time • Cons – Each new method will require its own delegate and new wiring.
  10. 10. DI via Mock POCOs • Initial Effort is medium – New class for each mock – Logic for mock states • Subsequent efforts – Potential for new forks (and bugs) in mock POCO logic for each use case • Pros – Don’t need to learn a new framework. • Cons – Supporting all use cases increases potential for bugs in the mocks. – Some dependencies can’t be mocked 1 1 – With Moq, you can only mock methods defined in an interface or virtual methods.
  11. 11. DI with Mocks (Moq) • Initial Effort is high – Each unit test use case requires its own moq wrapper per dependency • Subsequent changes – Only changes to the contract require modifications to your mocks • Pros – Each tests clearly identifies its assumptions • Cons – Lots of unit test code will just be setting up the dependency
  12. 12. Legacy Code: Static Methods • Interfaces can’t have static methods • Convert static methods to instance methods that conform to the (new) interface with a Singleton to expose the static instance.
  13. 13. Scenario Production issue with unknown cause • Scenario in production we can’t reproduce easily • In a unit test, mock the underlying interface to the throw the same exception. – At the very least, we’ll know how to stop this error from crashing the entire app and set up proper logging to identify potential causes
  14. 14. Scenario Production issue with unknown cause [Fact] public void TestIndex_WebExceptionFromReviewManager() { InjectCookieCollectionDependency(); var mock = new Mock<IReviewManager>(); mock.Setup(rm => rm.GetEsReviewsByMovie( It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<UserReviewSort>())) .Throws(new WebException()); IReviewManager reviewManager = mock.Object; using (var controller = new MovieController(reviewManager) { ControllerContext = new ControllerContext { HttpContext = new MockHttpContext() } }) { MockHttpContext httpContext = configureContext(UserAgentValue); controller.ControllerContext.HttpContext = httpContext; ActionResult result = controller.Index(MovieIdAmericanBeauty); Assert.IsType(typeof (ViewResult), result); } }
  15. 15. Scenario Anonymous + authenticated users • Our apps identify a logged in user by the presence of a cookie. We can mock that! – See changes to MovieController with ICustomerCookieProvider
  16. 16. Strategies for Unit Testing • New Projects – TDD allows us to work with QA to identify good test cases before we start writing code • Legacy Projects – Don’t test something that’s been working in production for years – Create unit tests to reproduce your bug. This will allow for immediate ROI on the tests – Introduce tests for new features
  17. 17. Side Effect (Good) • Enforces the SOLID principles Single Responsibility [link] If an interface crosses domains, you know to split them Multiple interfaces  too many responsibilities for the class Open/Closed Principle [link] Your code is inherently open to extension Liskov Substitution Principle [link] Your mocks provide are substituted for the concrete implementations without code changes Interface segregation Principle [link] Interface contract hides helper methods Dependency inversion principle [link] This is what we’re talking about here
  18. 18. Further Reading • Martin Fowler (http://martinfowler.com/articles/injection.html) • AutoFac IoC container(http://autofac.org/) • AutoFac in actionNuGet Gallery – DI by Environment

×