MSDN Magazine - March 2008 - (Page 57) Figure 3 Dependency Injection [Test] public void CanSubmitNewInvoice() { Invoice invoice = new Invoice(); ValidationResults validationResults = new ValidationResults(); IAuthorizationService authorizationService = mockery.CreateMock (); IInvoiceValidator invoiceValidator = mockery.CreateMock (); IInvoiceRepository invoiceRepository = mockery.CreateMock (); using(mockery.Record()) { Expect.Call(authorizationService.IsActionAllowed( invoice, InvoiceAction.Submit)).Return(true); Expect.Call(invoiceValidator.Validate(invoice)) .Return(validationResults); invoiceRepository.Save(invoice); new InvoiceService( new AuthorizationService(), new InvoiceValidator(), new InvoiceRepository())); As you can see, the UI would have to be aware of not just its own dependencies but also the dependencies of its dependencies, ad infinitum, down to the data layer. This is obviously not an ideal situation. The easiest way to solve this dilemma is with a technique that we’ll call the poor man’s dependency injection. Poor man’s dependency injection uses the default constructor of the higher-level component to supply the dependencies: public InvoiceService() : this(new AuthorizationService(), new InvoiceValidator(), new InvoiceRepository()) { } } } using(mockery.Playback()) { IInvoiceService service = new InvoiceService(authorizationService, invoiceValidator, invoiceRepository); service.Submit(invoice); } reconfigure the ServiceLocator to substitute an AuditingInvoiceRepository at deployment time for specific IInvoiceRepository requests. But even with these disadvantages, service location is easy to understand and better than hardcoding your dependencies. Notice how I’m delegating to the most overloaded constructor. This ensures that the class’s initialization logic is identical regardless of which constructor is used to create an instance. The only place the class is coupled to concrete dependencies is through the default constructor. The class remains testable because you still have the overloaded constructor that allows you to supply the class’s dependencies during unit testing. Containers Dependency Injection When unit testing a higher-level component, you want to provide fake or mock implementations for its dependencies. But rather than configuring a service locator with the fakes or mocks and then having the higher-level component look them up, you could just pass the dependencies directly to the higher-level component via a parameterized constructor. This technique is known as dependency injection. An example is shown in Figure 3. In this example, I’m creating mock objects for InvoiceService’s dependencies and then passing them to the InvoiceService constructor. (For more information on mock object frameworks, see Mark Seemann’s “Unit Testing: Exploring the Continuum of Test Doubles” at msdn.microsoft.com/msdnmag/issues/07/09/MockTesting.) In sum, you specify the behavior of the InvoiceService by defining how it will interact with the mocks rather than verifying the state of the InvoiceService after the test is run. By using dependency injection, you can easily supply your higherlevel components with their dependencies in unit tests. However, you still have the problem of how to locate a class’s dependencies outside of a unit test—either while running the application or in an integration test. It would be foolish to expect the UI layer to provide the service layer with its dependencies or the service layer to supply the repository layer with its dependencies. You would end up with an even worse problem than what you started with. But let’s suppose that the UI layer was responsible for supplying the service layer with its dependencies: // Somewhere in UI Layer InvoiceSubmissionPresenter presenter = new InvoiceSubmissionPresenter( Now it’s time to introduce inversion of control (IoC) containers, which provide a central place to manage dependencies. In reality, a container is nothing more than a fancy dictionary of interfaces versus implementing types. In its simplest form, an IoC container is just a service locator by a different name. Later on, I’ll examine how a container can do much more than just service location. Getting back to the problem at hand, you would like to completely decouple InvoiceService from concrete implementations of its dependencies. Like all problems in software, you can solve it by adding another layer of indirection. You introduce the notion of a dependency resolver, which maps an interface to a concrete implementation. You then use a generic method that takes an interface T and returns a type implementing that interface: public interface IDependencyResolver { T Resolve (); } Let’s implement the SimpleDependencyResolver, which uses a Figure 4 SimpleDependencyResolver public class SimpleDependencyResolver : IDependencyResolver { private readonly Dictionary m_Types = new Dictionary (); public T Resolve () { return (T)m_Types[typeof(T)]; } public void Register (object obj) { if(obj is T == false) { throw new InvalidOperationException( string.Format(“The supplied instance does not implement {0}”, typeof(T).FullName)); } m_Types.Add(typeof(T), obj); } } Dependency Injection march2008 57 http://msdn.microsoft.com/msdnmag/issues/07/09/MockTesting
Table of Contents Feed for the Digital Edition of MSDN Magazine - March 2008 MSDN Magazine - March 2008 Contents Toolbox CLR Inside Out Data Points Advanced Basics Office Space Introducing ASP.NET MVC Loosen Up CI Server Performance Office Development Test Run Security Briefs Extreme ASP.NET Foundations .NET Matters {End Bracket} MSDN Magazine - March 2008 MSDN Magazine - March 2008 - (Page Intro) MSDN Magazine - March 2008 - Contents (Page Cover1) MSDN Magazine - March 2008 - Contents (Page Cover2) MSDN Magazine - March 2008 - Contents (Page 1) MSDN Magazine - March 2008 - Contents (Page 2) MSDN Magazine - March 2008 - Contents (Page 3) MSDN Magazine - March 2008 - Contents (Page 4) MSDN Magazine - March 2008 - Contents (Page 5) MSDN Magazine - March 2008 - Contents (Page 6) MSDN Magazine - March 2008 - Contents (Page 7) MSDN Magazine - March 2008 - Contents (Page 8) MSDN Magazine - March 2008 - Contents (Page 9) MSDN Magazine - March 2008 - Contents (Page 10) MSDN Magazine - March 2008 - Toolbox (Page 11) MSDN Magazine - March 2008 - Toolbox (Page 12) MSDN Magazine - March 2008 - Toolbox (Page 13) MSDN Magazine - March 2008 - Toolbox (Page 14) MSDN Magazine - March 2008 - CLR Inside Out (Page 15) MSDN Magazine - March 2008 - CLR Inside Out (Page 16) MSDN Magazine - March 2008 - CLR Inside Out (Page 17) MSDN Magazine - March 2008 - CLR Inside Out (Page 18) MSDN Magazine - March 2008 - CLR Inside Out (Page 19) MSDN Magazine - March 2008 - CLR Inside Out (Page 20) MSDN Magazine - March 2008 - Data Points (Page 21) MSDN Magazine - March 2008 - Data Points (Page 22) MSDN Magazine - March 2008 - Data Points (Page 23) MSDN Magazine - March 2008 - Data Points (Page 24) MSDN Magazine - March 2008 - Data Points (Page 25) MSDN Magazine - March 2008 - Data Points (Page 26) MSDN Magazine - March 2008 - Advanced Basics (Page 27) MSDN Magazine - March 2008 - Advanced Basics (Page 28) MSDN Magazine - March 2008 - Advanced Basics (Page 29) MSDN Magazine - March 2008 - Advanced Basics (Page 30) MSDN Magazine - March 2008 - Advanced Basics (Page 31) MSDN Magazine - March 2008 - Advanced Basics (Page 32) MSDN Magazine - March 2008 - Office Space (Page 33) MSDN Magazine - March 2008 - Office Space (Page 34) MSDN Magazine - March 2008 - Office Space (Page 35) MSDN Magazine - March 2008 - Office Space (Page 36) MSDN Magazine - March 2008 - Office Space (Page 37) MSDN Magazine - March 2008 - Office Space (Page 38) MSDN Magazine - March 2008 - Office Space (Page 39) MSDN Magazine - March 2008 - Office Space (Page 40) MSDN Magazine - March 2008 - Office Space (Page 41) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 42) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 43) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 44) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 45) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 46) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 47) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 48) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 49) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 50) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 51) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 52) MSDN Magazine - March 2008 - Introducing ASP.NET MVC (Page 53) MSDN Magazine - March 2008 - Loosen Up (Page 54) MSDN Magazine - March 2008 - Loosen Up (Page 55) MSDN Magazine - March 2008 - Loosen Up (Page 56) MSDN Magazine - March 2008 - Loosen Up (Page 57) MSDN Magazine - March 2008 - Loosen Up (Page 58) MSDN Magazine - March 2008 - Loosen Up (Page 59) MSDN Magazine - March 2008 - Loosen Up (Page 60) MSDN Magazine - March 2008 - Loosen Up (Page 61) MSDN Magazine - March 2008 - Loosen Up (Page 62) MSDN Magazine - March 2008 - Loosen Up (Page 63) MSDN Magazine - March 2008 - Loosen Up (Page 64) MSDN Magazine - March 2008 - Loosen Up (Page 65) MSDN Magazine - March 2008 - Loosen Up (Page 66) MSDN Magazine - March 2008 - Loosen Up (Page 67) MSDN Magazine - March 2008 - Loosen Up (Page 68) MSDN Magazine - March 2008 - Loosen Up (Page 69) MSDN Magazine - March 2008 - CI Server (Page 70) MSDN Magazine - March 2008 - CI Server (Page 71) MSDN Magazine - March 2008 - CI Server (Page 72) MSDN Magazine - March 2008 - CI Server (Page 73) MSDN Magazine - March 2008 - CI Server (Page 74) MSDN Magazine - March 2008 - CI Server (Page 75) MSDN Magazine - March 2008 - CI Server (Page 76) MSDN Magazine - March 2008 - CI Server (Page 77) MSDN Magazine - March 2008 - CI Server (Page 78) MSDN Magazine - March 2008 - CI Server (Page 79) MSDN Magazine - March 2008 - CI Server (Page 80) MSDN Magazine - March 2008 - Performance (Page 81) MSDN Magazine - March 2008 - Performance (Page 82) MSDN Magazine - March 2008 - Performance (Page 83) MSDN Magazine - March 2008 - Performance (Page 84) MSDN Magazine - March 2008 - Performance (Page 85) MSDN Magazine - March 2008 - Performance (Page 86) MSDN Magazine - March 2008 - Performance (Page 87) MSDN Magazine - March 2008 - Performance (Page 88) MSDN Magazine - March 2008 - Office Development (Page 89) MSDN Magazine - March 2008 - Office Development (Page 90) MSDN Magazine - March 2008 - Office Development (Page 91) MSDN Magazine - March 2008 - Office Development (Page 92) MSDN Magazine - March 2008 - Office Development (Page 93) MSDN Magazine - March 2008 - Office Development (Page 94) MSDN Magazine - March 2008 - Office Development (Page 95) MSDN Magazine - March 2008 - Office Development (Page 96) MSDN Magazine - March 2008 - Test Run (Page 97) MSDN Magazine - March 2008 - Test Run (Page 98) MSDN Magazine - March 2008 - Test Run (Page 99) MSDN Magazine - March 2008 - Test Run (Page 100) MSDN Magazine - March 2008 - Test Run (Page 101) MSDN Magazine - March 2008 - Test Run (Page 102) MSDN Magazine - March 2008 - Test Run (Page 103) MSDN Magazine - March 2008 - Test Run (Page 104) MSDN Magazine - March 2008 - Test Run (Page 105) MSDN Magazine - March 2008 - Test Run (Page 106) MSDN Magazine - March 2008 - Security Briefs (Page 107) MSDN Magazine - March 2008 - Security Briefs (Page 108) MSDN Magazine - March 2008 - Security Briefs (Page 109) MSDN Magazine - March 2008 - Security Briefs (Page 110) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 111) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 112) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 113) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 114) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 115) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 116) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 117) MSDN Magazine - March 2008 - Extreme ASP.NET (Page 118) MSDN Magazine - March 2008 - Foundations (Page 119) MSDN Magazine - March 2008 - Foundations (Page 120) MSDN Magazine - March 2008 - Foundations (Page 121) MSDN Magazine - March 2008 - Foundations (Page 122) MSDN Magazine - March 2008 - Foundations (Page 123) MSDN Magazine - March 2008 - Foundations (Page 124) MSDN Magazine - March 2008 - Foundations (Page 125) MSDN Magazine - March 2008 - Foundations (Page 126) MSDN Magazine - March 2008 - Foundations (Page 127) MSDN Magazine - March 2008 - Foundations (Page 128) MSDN Magazine - March 2008 - .NET Matters (Page 129) MSDN Magazine - March 2008 - .NET Matters (Page 130) MSDN Magazine - March 2008 - .NET Matters (Page 131) MSDN Magazine - March 2008 - {End Bracket} (Page 132) MSDN Magazine - March 2008 - {End Bracket} (Page Cover3) MSDN Magazine - March 2008 - {End Bracket} (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.