240 likes | 552 Views
Real world TDD + Dependency Injection. Rob Fonseca-Ensor Datacom Systems. I’m Rob Fonseca-Ensor From Datacom (www.datacom.co.nz) www.robfe.com rob@robfe.com www.twitter.com/robfe. Introductions. Unit testing & TDD How Inversion of Control helps you TDD
E N D
Real world TDD + Dependency Injection Rob Fonseca-Ensor Datacom Systems
I’m Rob Fonseca-Ensor From Datacom (www.datacom.co.nz) www.robfe.com rob@robfe.com www.twitter.com/robfe Introductions
Unit testing & TDD How Inversion of Control helps you TDD How Dependency Injection helps you IOC Build your own DI container Using the Microsoft Unity container Other DI containers Agenda
Plain Old Unit Testing • Verification of isolated “units” of code • Automated • Self-Verifying • Repeatable • Just call a method and check its results • Linear • Easy to read • MsUnit is built into most versions of Visual Studio • Open source frameworks available too
What is TDD • Write a test for whatever feature you’re about to develop • Ensure the test fails (important) • Develop the feature • Ensure the test passes (also important)
Why TDD • Increased code coverage (Same as POUT?) • Refactorable • Understandable (better than comments) • Better code design (TDD only) • Forces a conscious design of method signatures • Requirements problems will be raised sooner • Code complex functionality faster (TDD only) • Start small, and make little improvements • Positive reinforcement at every step • Faster "code - compile - check" cycle
Why TDD Saves Time • You can fix bad code without worry • Just run the tests after “fixing” it • You can understand code faster • The tests offer a verifiable narrative • Play with the code and see what breaks • It’s easier to build the code in the first place • The code will be better designed • Business requirements • Software structure
Starting out with TDD Learning curve Test Maintenance Sweet http://xunitpatterns.com/Goals%20of%20Test%20Automation.html
When does TDD hurt? • Very low level • Check that a property setter works • Too slow to develop • Often pointless • Very high level / coarse functions • Too hard to develop • Often useful (but treat them as “Integration Tests”) • External dependencies / process boundaries • Too fragile • Too slow to run
TDD: Easy and Hard examples double Total(Expense[] es) void Claim(Expense e) Specification: All valid claims should be saved If a claim is over $200, send an email to the receptionist If the person’s total claims for the month are over $1000, send an email to the receptionist Depends on Database Email infrastructure Logic is tied to data Data query is tied to logic Don’t call db if claim not valid No return value Where’s the result • Specification: • Iterate through all the expenses • Add up the “Amount” • Return the result • No dependencies • Logic is the same all the time • Easy to inspect result
How IOC helps TDD • Usually, a component will “new” up whatever it needs to get the job done • SqlConnection / OracleConnection • SmtpClient • HttpWebRequest • With IOC, the component is no longer in control of what its dependencies are • It should interact with its dependencies through interfaces, instead of directly via classes • Tests can substitute test doubles in place of real dependencies • Mocks, Stubs etc • Mock objects will let you test components from both ends of the stack! • AKA GOF “Strategy Pattern”
IOC Example NO IOC WITH IOC public class Alerter { private IEmailer emailer; public Alerter(IEmailer emailer) { this.emailer = emailer; } public void Alert(string recipient) { emailer.SendMail( recipient, "Danger", "High voltage!"); } } public class Alerter { public void Alert(string recipient) { SmtpEmailer e = new SmtpEmailer(); e.SendMail( recipient, "Danger", "High voltage!"); } }
Other advantages of IOC • MUCH easier to write “Single Responsibility” classes • Easy to swap out implementations • Adding features • Different flavour of database • New web service API • Install-specific customisation • Different business rule modules per site • Easy to reuse existing code • Services can be chained • AuditingRepository wraps IRepository
IOC in production • Dependency hierarchies need to be built • Web page depends on ILogic • Logic depends on IRepository (data access) • Logic depends on IEmailer • Repository depends on IDBConnection • Hand coding a hierarchy gets tiresome • Especially if you have to swap a dependency
Dependency Injection • A framework to provide concrete implementations to your components • Single point of configuration • *.config • Global.asax • Program.cs • Should handle dependency chains / hierarchies
Demo: DIY DI • Lets build our own DI container • See how they work • Simple container: • Supports registering types • Supports resolving types • Sub-dependencies are resolved too • See www.kenegozi.com
DIY DI • Don’t want to download and package yet another DLL? • Paste my code into your app • Upgrade when you need to • Watch my blog for a bigger (50 line) DI container • Support for named parameters • Support for component lifestyles • Transient / Singleton
“Proper” DI Containers • More features than we’ve just covered: • Error handling • Named parameters • Property/Method injection • AOP • Configuration • XML • Fluent • Ease of use • Performance • Reflection vs. Dynamic MSIL generation • Component pooling
Microsoft Unity • http://www.codeplex.com/unity • MS-PL License • Built on ObjectBuilder • Better at “injection” • Configuration is simpler • More lightweight • Lots of videos! Check out the website • Might be part of .Net one day
Unity Demo • What the app does • The service interfaces used • The tests • The components • The components’ unity bits • Global.asaxconfig
Other DI frameworks • Castle Windsor • Mature • Widely used • Excellent AOP support • Comes with my personal stamp of approval • 2 projects in production with Castle • Spring .Net • Mature • Widely used • Excellent AOP support
Other DI frameworks • Ninject • Excellent “Dojo” • High performance for transient components • Well designed extensibility • Castle’s AOP support can be plugged in • And more!
Links • Testing patterns (good theory) http://xunitpatterns.com • Scott’s roundup http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx • A bigger D.I.Y. DI container (coming soon) http://www.robfe.com • James Kovacs’ MSDN Article on DI http://msdn.microsoft.com/en-ca/magazine/cc337885.aspx • The Ninject Dojo (good theory) http://ninject.org/learn