real world tdd + dependency injection

24
Real world TDD + Dependency Injection Rob Fonseca-Ensor Datacom Systems

Upload: damali

Post on 23-Feb-2016

63 views

Category:

Documents


0 download

DESCRIPTION

Real world TDD + Dependency Injection. Rob Fonseca-Ensor Datacom Systems. I’m Rob Fonseca-Ensor From Datacom (www.datacom.co.nz) www.robfe.com [email protected] www.twitter.com/robfe. Introductions. Unit testing & TDD How Inversion of Control helps you TDD - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Real world TDD + Dependency Injection

Real world TDD + Dependency Injection

Rob Fonseca-EnsorDatacom Systems

Page 2: Real world TDD + Dependency Injection

Introductions• I’m Rob Fonseca-Ensor• From Datacom (www.datacom.co.nz)

www.robfe.com

[email protected]

www.twitter.com/robfe

Page 3: Real world TDD + Dependency Injection

Agenda• 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

Page 4: Real world TDD + Dependency Injection

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

Page 5: Real world TDD + Dependency Injection

What is TDD

1. Write a test for whatever feature you’re about to develop

2. Ensure the test fails (important)3. Develop the feature4. Ensure the test passes (also important)

Page 6: Real world TDD + Dependency Injection

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

Page 7: Real world TDD + Dependency Injection

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

Page 8: Real world TDD + Dependency Injection

Starting out with TDD

http://xunitpatterns.com/Goals%20of%20Test%20Automation.html

Learning curve

Sweet

Test Maintenance

Page 9: Real world TDD + Dependency Injection

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

Page 10: Real world TDD + Dependency Injection

TDD: Easy and Hard examplesdouble Total(Expense[] es)• Specification:

1. Iterate through all the expenses

2. Add up the “Amount”3. Return the result

• No dependencies• Logic is the same all the

time• Easy to inspect result

void Claim(Expense e)• Specification:

1. All valid claims should be saved2. If a claim is over $200, send an email to the

receptionist3. 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

Page 11: Real world TDD + Dependency Injection

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”

Page 12: Real world TDD + Dependency Injection

IOC ExampleNO IOCpublic class Alerter{ public void Alert(string recipient) { SmtpEmailer e = new SmtpEmailer(); e.SendMail( recipient, "Danger", "High voltage!"); }}

WITH IOCpublic class Alerter{ private IEmailer emailer;

public Alerter(IEmailer emailer) { this.emailer = emailer; }

public void Alert(string recipient) { emailer.SendMail( recipient, "Danger", "High voltage!"); }}

Page 13: Real world TDD + Dependency Injection

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

Page 14: Real world TDD + Dependency Injection

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

Page 15: Real world TDD + Dependency Injection

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

Page 16: Real world TDD + Dependency Injection

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

Page 17: Real world TDD + Dependency Injection

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

Page 18: Real world TDD + Dependency Injection

“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

Page 19: Real world TDD + Dependency Injection

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

Page 20: Real world TDD + Dependency Injection

Unity Demo• What the app does• The service interfaces used• The tests• The components• The components’ unity bits• Global.asax config

Page 21: Real world TDD + Dependency Injection

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

Page 22: Real world TDD + Dependency Injection

Other DI frameworks• Ninject

– Excellent “Dojo”– High performance for transient components– Well designed extensibility

• Castle’s AOP support can be plugged in• And more!

Page 23: Real world TDD + Dependency Injection

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 DIhttp://msdn.microsoft.com/en-ca/magazine/cc337885.aspx

• The Ninject Dojo (good theory)http://ninject.org/learn

Page 24: Real world TDD + Dependency Injection

Questions?