MSDN Magazine - March 2008 - (Page 55) ensure that each test’s initial data is independent of other tests’ initial data, or you can run into test ordering problems where certain tests fail if run out of order. MaintainHow confident are you that your data layer will only talk ing the database in a known good state is time-consuming to SQL Server® or that you’ll always load your app settings and error prone. from an XML document named Settings.xml? The intent Additionally, if you need to change the implementation of here is not to build an infinitely extensible but hugely coma lower layer, you’re often forced to modify the upper layers Figure 1 plex and unusable generic framework. It is about reversibilas well due to implicit or explicit dependencies that those Typical ity. How easily can you change your mind with respect to layers have on the lower layer. Although you have layered Layered design decisions? Do you have an application architecture Architecture the application, you have not achieved loose coupling. that responds well to change? Let’s take a look at a concrete example—a service that acWhy am I worried about change? Because practically the only cepts invoices (see Figure 2). For InvoiceService.Submit to be able constant in this industry is change. Requirements change, tech- to accept an invoice submission, it depends on an Authorizationnologies change, developers change, and the business changes. Are Service, InvoiceValidator, and InvoiceRepository, which are creyou putting yourself in a position to respond to those changes? By ated in the class’s constructor. You cannot unit test InvoiceService creating loosely coupled designs, software can better respond to without its concrete dependencies. This means that before you run inevitable, and many times unforeseeable, changes. your unit tests, you must ensure that the database is in a state such that you will not cause any primary or unique key violations when The Inner Dependency Problem InvoiceRepository inserts the new invoice, nor must InvoiceValiLet’s examine a typical highly coupled design that you’ll find in dator report any validation failures. You must also ensure that the your average layered application architecture (see Figure 1). A simple user running the unit tests has the correct permissions so that Aulayering scheme has a UI layer that talks to a service (or business) thorizationService will permit the “Submit” operation. layer that talks to a repository (or data) layer. The dependencies beThat is a tall order. If there are problems in any of these dependent tween these layers flow the same way down. The repository layer is components, either code or data errors, the InvoiceService tests will unaware of the service layer, which is unaware of the UI layer. fail unexpectedly. Even if the test passes, the total execution time Sometimes you have a few more layers, such as a presentation will be a few hundred milliseconds between setting up the correct or workflow layer, but the pattern of layers being aware only of the data in the database, executing the tests, and cleaning up any data layer beneath them is fairly typical. Layers as coherent clusters of created by the test. Even if you amortize the cost of the setup and responsibility are a good design technique. Direct coupling of upper layers to lower layers, however, increases coupling and makes Figure 2 Invoice Service the application difficult to test. public class InvoiceService { Why am I concerned with testability? Because testability is a good private readonly AuthorizationService authoriazationService; private readonly InvoiceValidator invoiceValidator; barometer of coupling. If you can’t easily instantiate a class in a test, private readonly InvoiceRepository invoiceRepository; you have a coupling problem. For example, the service layer is inpublic InvoiceService() { timately familiar with and dependent on the repository layer. We authoriazationService = new AuthorizationService(); cannot test the service layer in isolation of the repository layer. On invoiceValidator = new InvoiceValidator(); invoiceRepository = new InvoiceRepository(); a practical level, this means that most tests access the underlying } database, file system, or network. This leads to a variety of probpublic ValidationResults Submit(Invoice invoice) { lems, including slow tests and high maintenance costs. ValidationResults results; Slow Tests If tests can execute strictly in memory, time per test CheckPermissions(invoice, InvoiceAction.Submit); results = ValidateInvoice(invoice); can be in the millisecond range. If tests access external resources, SaveInvoice(invoice); such as a database, file system, or network, time per test is often return results; } 100 milliseconds or more. Considering that a typical project with good test coverage has hundreds or thousands of tests, this can private void CheckPermissions(Invoice invoice, InvoiceAction action) { if(authoriazationService.IsActionAllowed(invoice, action) == false) { mean the difference between running your tests in a few seconds throw new SecurityException( versus minutes or hours. “Insufficient permissions to submit this invoice”); } Poor Error Isolation A failure in a data layer component often } causes tests of upper-layer components to fail, too. Rather than private ValidationResults ValidateInvoice(Invoice invoice) { having a few tests fail, which helps you quickly isolate the probreturn invoiceValidator.Validate(invoice); lem, you have hundreds of failing tests, which makes finding the } problem difficult and more time-consuming. private void SaveInvoice(Invoice invoice) { High Maintenance Costs Most tests require some initial data. invoiceRepository.Save(invoice); } If those tests touch the database, you must ensure that your da} tabase is in a known state before each test. In addition, you must Or even this one: XmlDocument settings = new XmlDocument(); settings.Load(“Settings.xml”); march2008 55
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.