SlideShare a Scribd company logo
1 of 59
Breaking Dependencies
to Allow UnitTesting
Steve Smith
Ardalis Services
@ardalis | ardalis.com
Tweet Away
• LiveTweeting and Photos are encouraged
• Questions and Feedback are welcome
• Use #DevIntersection and/or #breakDependencies
• Or #DevIntersectionBreakingDependenciesToAllowUnitTesting (55 chars with space)
Pluralsight
I have some 1-month free
passes; see me after if
you’d like one
Questions up Front
What kinds of dependencies in your code cause you the most pain today?
Legacy Code
“To me, legacy code is simply code without tests.”
Michael Feathers
Working Effectively with Legacy Code
UnitTesting (Legacy) Code is…
Here’s (Mostly)Why…
Hollywood made a whole movie about it…
But let’s back up…
• Why UnitTests?
• Why not just use other kinds of tests?
• What are dependencies?
• How do we break these dependencies?
UnitTests Prevent SmallThermal Exhaust Ports inYour Code
UnitTest Characteristics
• Test a single unit of code
• A method, or at most, a class
• Do not test Infrastructure concerns
• Database, filesystem, etc.
• Do not test “through” the UI
• Just code testing code; no screen readers, etc.
UnitTests are (should be) FAST
• No dependencies means
1000s of tests per second
• Run them constantly
UnitTests are SMALL
• Testing one thing should be simple
• If not, can it be made simpler?
• Should be quick to write
UnitTest Naming
• Descriptive And Meaningful Phrases (DAMP)
• NameTest Class: ClassNameMethodName
• NameTest Method: DoesSomethingGivenSomething
• http://ardalis.com/unit-test-naming-convention
Seams
• Represent areas of code where pieces can be decoupled
• Testable code has many seams; legacy code has few, if any
Kinds ofTests
UI
IntegrationTests
UnitTests
http://martinfowler.com/bliki/TestPyramid.html
Ask yourself:
•Can I test this scenario with a UnitTest?
•Can I test it with an IntegrationTest?
• Can I test it with an automated UITest?
UI
Integration Tests
UnitTests
Don’t believe your test runner…
IntegrationTest
UnitTest?
• Requires a database or file?
• Sends emails?
• Must be executed through the UI?
Not a unit test
Dependencies and Coupling
All dependencies point toward
infrastructure
Presentation
Layer
Business Layer
Infrastructure
Data Access
Tests
Tests (and everything else) now
depend on Infrastructure
Dependency Inversion Principle
High-level modules should not depend on low-level modules. Both should
depend on abstractions.
Abstractions should not depend on details. Details should depend on
abstractions.
Agile Principles, Patterns, and Practices in C#
Depend on Abstractions
All dependencies point
toward Business Logic /
CorePresentation Layer
Business Layer
Infrastructure
DataAccess
UnitTests
IntegrationTestsUITests
Inject Dependencies
• Classes should follow Explicit Dependencies Principle
• http://deviq.com/explicit-dependencies-principle
• Prefer Constructor Injection
• Classes cannot be created in an invalid state
https://flic.kr/p/5QsGnB
Common Dependencies to Decouple
•Database
•File System
•Email
•Web APIs
•System Clock
•Configuration
•Thread.Sleep
•Random
Tight Couplers: Statics and new
• Avoid static cling
• Calling static methods with side effects
• Remember: new is glue
• Avoid gluing your code to a specific implementation
• Simple types and value objects usually OK
http://ardalis.com/new-is-glue
Coupling Code Smells
• Learn more in my Refactoring Fundamentals course on Pluralsight
• http://www.pluralsight.com/courses/refactoring-fundamentals
• Coupling Smells introduce tight coupling between parts of a system
Feature Envy
• Characterized by many getter calls
• Violates the “Tell, Don’tAsk” principle
• Instead, try to package data and behavior together
• Keep together things that change together
• Common Closure Principle – Classes that change together are packaged together
Law of Demeter
• Or the “StronglyWorded Suggestion of Demeter”
• A Method m on an object O should only call methods on
• O itself
• m’s parameters
• Objects created within m
• O’s direct fields and properties
• Global variables and static methods
Law of Demeter
Law of Demeter
Law of Demeter
http://geek-and-poke.com
Constructors
Explicit Dependencies Principle
• Methods and classes should require their collaborators as parameters
• Objects should never exist in an invalid state
http://deviq.com/explicit-dependencies-principle/
Constructor Smells
• new keyword (or static calls) in constructor or field declaration
• Anything more than field assignment!
• Database access in constructor
• Complex object graph construction
• Conditionals or Loops
Good Constructors
• Do not create collaborators, but instead accept them as parameters
• Use a Factory for complex object graph creation
• Avoid instantiating fields at declaration
“
”
IoC Containers are just factories on
steroids.
Don’t be afraid to use them where they can help
Avoid Initialize Methods
• Moving code out of the constructor and into Init()
• If called from constructor, no different
• If called later, leaves object in invalid state until called
• Object has too many responsibilities
• If Initialize depends on infrastructure, object will still be hard to test
“Test” Constructors
• “It’s OK, I’ll provide an “extra” constructor my tests can use!”
• Great! As long as we don’t have to test any other classes that use the other
constructor.
Avoid Digging into Collaborators
• Pass in the specific object(s) you need
• Avoid using “Context” or “Manager” objects to access additional
dependencies
• Violates Law of Demeter: Context.SomeItem.Foo()
• Suspicious Names: environment, principal, container
• Symptoms:Tests have mocks that return mocks
Avoid Global State Access
• Singletons
• Static fields or methods
• Static initializers
• Registries
• Service Locators
Singletons
• Avoid classes that implement their own lifetime tracking
• GoF Singleton Pattern
• It’s OK to have a container manage object lifetime and enforce having only a
single instance of a class within your application
Breaking Dependencies inWeb Forms
Demo
Answer Questions
Demo
Summary
• Inject Dependencies
• Remember “New is glue”.
• Keep yourAPIs honest
• Remember the Explicit Dependencies Principle.Tell your friends.
• Maintain seams and keep coupling loose
Thanks!
• Questions?
• Follow me at @ardalis
• Check out http://DevIQ.com for more on these topics
• Take Pride inYour Code!
• References
• http://misko.hevery.com/code-reviewers-guide/
• Working Effectively with Legacy Code
by Michael Feathers
Please use Event Board
to fill out a session evaluation.

More Related Content

What's hot

Software Engineering - chp7- tests
Software Engineering - chp7- testsSoftware Engineering - chp7- tests
Software Engineering - chp7- tests
Lilia Sfaxi
 
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
seleniumconf
 

What's hot (20)

Automated Acceptance Tests in .NET
Automated Acceptance Tests in .NETAutomated Acceptance Tests in .NET
Automated Acceptance Tests in .NET
 
Getting Started with Selenium
Getting Started with SeleniumGetting Started with Selenium
Getting Started with Selenium
 
Selenium Frameworks
Selenium FrameworksSelenium Frameworks
Selenium Frameworks
 
How To Use Selenium Successfully
How To Use Selenium SuccessfullyHow To Use Selenium Successfully
How To Use Selenium Successfully
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Power-Up Your Test Suite with OLE Automation by Joshua Russell
Power-Up Your Test Suite with OLE Automation by Joshua RussellPower-Up Your Test Suite with OLE Automation by Joshua Russell
Power-Up Your Test Suite with OLE Automation by Joshua Russell
 
Testing Java EE apps with Arquillian
Testing Java EE apps with ArquillianTesting Java EE apps with Arquillian
Testing Java EE apps with Arquillian
 
Selenium Users Anonymous
Selenium Users AnonymousSelenium Users Anonymous
Selenium Users Anonymous
 
Software Engineering - chp7- tests
Software Engineering - chp7- testsSoftware Engineering - chp7- tests
Software Engineering - chp7- tests
 
Acceptance Test Driven Development With Spec Flow And Friends
Acceptance Test Driven Development With Spec Flow And FriendsAcceptance Test Driven Development With Spec Flow And Friends
Acceptance Test Driven Development With Spec Flow And Friends
 
Unit testing - A&BP CC
Unit testing - A&BP CCUnit testing - A&BP CC
Unit testing - A&BP CC
 
How To Find Information On Your Own
How To Find Information On Your OwnHow To Find Information On Your Own
How To Find Information On Your Own
 
Getting Ahead of Delivery Issues with Deep SDLC Analysis by Donald Belcham
Getting Ahead of Delivery Issues with Deep SDLC Analysis by Donald BelchamGetting Ahead of Delivery Issues with Deep SDLC Analysis by Donald Belcham
Getting Ahead of Delivery Issues with Deep SDLC Analysis by Donald Belcham
 
Bdd and spec flow
Bdd and spec flowBdd and spec flow
Bdd and spec flow
 
Testable requirements
Testable requirementsTestable requirements
Testable requirements
 
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
 
Automated Acceptance Test Practices and Pitfalls
Automated Acceptance Test Practices and PitfallsAutomated Acceptance Test Practices and Pitfalls
Automated Acceptance Test Practices and Pitfalls
 
Как стать синьором
Как стать синьоромКак стать синьором
Как стать синьором
 
TDD and BDD and ATDD
TDD and BDD and ATDDTDD and BDD and ATDD
TDD and BDD and ATDD
 
Behavior Driven Development with SpecFlow
Behavior Driven Development with SpecFlowBehavior Driven Development with SpecFlow
Behavior Driven Development with SpecFlow
 

Similar to Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016

Unit Testing Best Practices
Unit Testing Best PracticesUnit Testing Best Practices
Unit Testing Best Practices
Tomaš Maconko
 
Type mock isolator
Type mock isolatorType mock isolator
Type mock isolator
MaslowB
 
Best practices for writing good automated tests
Best practices for writing good automated testsBest practices for writing good automated tests
Best practices for writing good automated tests
Felipe Lima
 
An Introduction to unit testing
An Introduction to unit testingAn Introduction to unit testing
An Introduction to unit testing
Steven Casey
 

Similar to Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016 (20)

Unit Testing
Unit TestingUnit Testing
Unit Testing
 
An Introduction to Unit Testing
An Introduction to Unit TestingAn Introduction to Unit Testing
An Introduction to Unit Testing
 
Agile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayAgile Software Testing the Agilogy Way
Agile Software Testing the Agilogy Way
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
CNUG TDD June 2014
CNUG TDD June 2014CNUG TDD June 2014
CNUG TDD June 2014
 
Summit 16: Stop Writing Legacy Code!
Summit 16: Stop Writing Legacy Code!Summit 16: Stop Writing Legacy Code!
Summit 16: Stop Writing Legacy Code!
 
Microsoft Fakes, Unit Testing the (almost) Untestable Code
Microsoft Fakes, Unit Testing the (almost) Untestable CodeMicrosoft Fakes, Unit Testing the (almost) Untestable Code
Microsoft Fakes, Unit Testing the (almost) Untestable Code
 
Unit Tests with Microsoft Fakes
Unit Tests with Microsoft FakesUnit Tests with Microsoft Fakes
Unit Tests with Microsoft Fakes
 
An Introduction to Unit Testing
An Introduction to Unit TestingAn Introduction to Unit Testing
An Introduction to Unit Testing
 
Working with Legacy Code
Working with Legacy CodeWorking with Legacy Code
Working with Legacy Code
 
Unit Testing Best Practices
Unit Testing Best PracticesUnit Testing Best Practices
Unit Testing Best Practices
 
Introduction to Dependency Injection
Introduction to Dependency InjectionIntroduction to Dependency Injection
Introduction to Dependency Injection
 
Type mock isolator
Type mock isolatorType mock isolator
Type mock isolator
 
2020-Feb: Testing: Cables and Chains
2020-Feb: Testing: Cables and Chains2020-Feb: Testing: Cables and Chains
2020-Feb: Testing: Cables and Chains
 
Embedded world 2017
Embedded world 2017Embedded world 2017
Embedded world 2017
 
Best practices for writing good automated tests
Best practices for writing good automated testsBest practices for writing good automated tests
Best practices for writing good automated tests
 
Unit Testing and Tools
Unit Testing and ToolsUnit Testing and Tools
Unit Testing and Tools
 
An Introduction to unit testing
An Introduction to unit testingAn Introduction to unit testing
An Introduction to unit testing
 
Entity Framework: To the Unit of Work Design Pattern and Beyond
Entity Framework: To the Unit of Work Design Pattern and BeyondEntity Framework: To the Unit of Work Design Pattern and Beyond
Entity Framework: To the Unit of Work Design Pattern and Beyond
 
Qt test framework
Qt test frameworkQt test framework
Qt test framework
 

More from Steven Smith

More from Steven Smith (20)

Clean architecture with asp.net core by Ardalis
Clean architecture with asp.net core by ArdalisClean architecture with asp.net core by Ardalis
Clean architecture with asp.net core by Ardalis
 
Finding Patterns in the Clouds - Cloud Design Patterns
Finding Patterns in the Clouds - Cloud Design PatternsFinding Patterns in the Clouds - Cloud Design Patterns
Finding Patterns in the Clouds - Cloud Design Patterns
 
Introducing domain driven design - dogfood con 2018
Introducing domain driven design - dogfood con 2018Introducing domain driven design - dogfood con 2018
Introducing domain driven design - dogfood con 2018
 
Introducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashIntroducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemash
 
Most Useful Design Patterns
Most Useful Design PatternsMost Useful Design Patterns
Most Useful Design Patterns
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing Software
 
Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0
 
Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain Events
 
A Whirldwind Tour of ASP.NET 5
A Whirldwind Tour of ASP.NET 5A Whirldwind Tour of ASP.NET 5
A Whirldwind Tour of ASP.NET 5
 
Domain events
Domain eventsDomain events
Domain events
 
My Iraq Experience
My Iraq ExperienceMy Iraq Experience
My Iraq Experience
 
Add Some DDD to Your ASP.NET MVC, OK?
Add Some DDD to Your ASP.NET MVC, OK?Add Some DDD to Your ASP.NET MVC, OK?
Add Some DDD to Your ASP.NET MVC, OK?
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC
 
Refactoring with SOLID Principles (FalafelCon 2013)
Refactoring with SOLID Principles (FalafelCon 2013)Refactoring with SOLID Principles (FalafelCon 2013)
Refactoring with SOLID Principles (FalafelCon 2013)
 
Common ASP.NET Design Patterns - Telerik India DevCon 2013
Common ASP.NET Design Patterns - Telerik India DevCon 2013Common ASP.NET Design Patterns - Telerik India DevCon 2013
Common ASP.NET Design Patterns - Telerik India DevCon 2013
 
Refactoring with SOLID - Telerik India DevCon 2013
Refactoring with SOLID - Telerik India DevCon 2013Refactoring with SOLID - Telerik India DevCon 2013
Refactoring with SOLID - Telerik India DevCon 2013
 
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID Principles
 
Common asp.net design patterns aspconf2012
Common asp.net design patterns aspconf2012Common asp.net design patterns aspconf2012
Common asp.net design patterns aspconf2012
 
Common design patterns (migang 16 May 2012)
Common design patterns (migang 16 May 2012)Common design patterns (migang 16 May 2012)
Common design patterns (migang 16 May 2012)
 
Introducing Pair Programming
Introducing Pair ProgrammingIntroducing Pair Programming
Introducing Pair Programming
 

Recently uploaded

%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 

Recently uploaded (20)

WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - Kanchana
 
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
WSO2Con2024 - Navigating the Digital Landscape: Transforming Healthcare with ...
 
WSO2CON 2024 Slides - Unlocking Value with AI
WSO2CON 2024 Slides - Unlocking Value with AIWSO2CON 2024 Slides - Unlocking Value with AI
WSO2CON 2024 Slides - Unlocking Value with AI
 
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...
WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...
WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 

Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016

  • 1. Breaking Dependencies to Allow UnitTesting Steve Smith Ardalis Services @ardalis | ardalis.com
  • 2. Tweet Away • LiveTweeting and Photos are encouraged • Questions and Feedback are welcome • Use #DevIntersection and/or #breakDependencies • Or #DevIntersectionBreakingDependenciesToAllowUnitTesting (55 chars with space)
  • 3. Pluralsight I have some 1-month free passes; see me after if you’d like one
  • 4. Questions up Front What kinds of dependencies in your code cause you the most pain today?
  • 5. Legacy Code “To me, legacy code is simply code without tests.” Michael Feathers Working Effectively with Legacy Code
  • 8. Hollywood made a whole movie about it…
  • 9. But let’s back up… • Why UnitTests? • Why not just use other kinds of tests? • What are dependencies? • How do we break these dependencies?
  • 10. UnitTests Prevent SmallThermal Exhaust Ports inYour Code
  • 11. UnitTest Characteristics • Test a single unit of code • A method, or at most, a class • Do not test Infrastructure concerns • Database, filesystem, etc. • Do not test “through” the UI • Just code testing code; no screen readers, etc.
  • 12. UnitTests are (should be) FAST • No dependencies means 1000s of tests per second • Run them constantly
  • 13. UnitTests are SMALL • Testing one thing should be simple • If not, can it be made simpler? • Should be quick to write
  • 14. UnitTest Naming • Descriptive And Meaningful Phrases (DAMP) • NameTest Class: ClassNameMethodName • NameTest Method: DoesSomethingGivenSomething • http://ardalis.com/unit-test-naming-convention
  • 15. Seams • Represent areas of code where pieces can be decoupled • Testable code has many seams; legacy code has few, if any
  • 17. Ask yourself: •Can I test this scenario with a UnitTest? •Can I test it with an IntegrationTest? • Can I test it with an automated UITest? UI Integration Tests UnitTests
  • 18. Don’t believe your test runner… IntegrationTest
  • 19. UnitTest? • Requires a database or file? • Sends emails? • Must be executed through the UI? Not a unit test
  • 20. Dependencies and Coupling All dependencies point toward infrastructure Presentation Layer Business Layer Infrastructure Data Access Tests Tests (and everything else) now depend on Infrastructure
  • 21. Dependency Inversion Principle High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. Agile Principles, Patterns, and Practices in C#
  • 22. Depend on Abstractions All dependencies point toward Business Logic / CorePresentation Layer Business Layer Infrastructure DataAccess UnitTests IntegrationTestsUITests
  • 23. Inject Dependencies • Classes should follow Explicit Dependencies Principle • http://deviq.com/explicit-dependencies-principle • Prefer Constructor Injection • Classes cannot be created in an invalid state https://flic.kr/p/5QsGnB
  • 24. Common Dependencies to Decouple •Database •File System •Email •Web APIs •System Clock •Configuration •Thread.Sleep •Random
  • 25. Tight Couplers: Statics and new • Avoid static cling • Calling static methods with side effects • Remember: new is glue • Avoid gluing your code to a specific implementation • Simple types and value objects usually OK http://ardalis.com/new-is-glue
  • 26. Coupling Code Smells • Learn more in my Refactoring Fundamentals course on Pluralsight • http://www.pluralsight.com/courses/refactoring-fundamentals • Coupling Smells introduce tight coupling between parts of a system
  • 27. Feature Envy • Characterized by many getter calls • Violates the “Tell, Don’tAsk” principle • Instead, try to package data and behavior together • Keep together things that change together • Common Closure Principle – Classes that change together are packaged together
  • 28.
  • 29.
  • 30. Law of Demeter • Or the “StronglyWorded Suggestion of Demeter” • A Method m on an object O should only call methods on • O itself • m’s parameters • Objects created within m • O’s direct fields and properties • Global variables and static methods
  • 36. Explicit Dependencies Principle • Methods and classes should require their collaborators as parameters • Objects should never exist in an invalid state http://deviq.com/explicit-dependencies-principle/
  • 37. Constructor Smells • new keyword (or static calls) in constructor or field declaration • Anything more than field assignment! • Database access in constructor • Complex object graph construction • Conditionals or Loops
  • 38. Good Constructors • Do not create collaborators, but instead accept them as parameters • Use a Factory for complex object graph creation • Avoid instantiating fields at declaration
  • 39. “ ” IoC Containers are just factories on steroids. Don’t be afraid to use them where they can help
  • 40.
  • 41.
  • 42.
  • 43.
  • 44. Avoid Initialize Methods • Moving code out of the constructor and into Init() • If called from constructor, no different • If called later, leaves object in invalid state until called • Object has too many responsibilities • If Initialize depends on infrastructure, object will still be hard to test
  • 45.
  • 46.
  • 47. “Test” Constructors • “It’s OK, I’ll provide an “extra” constructor my tests can use!” • Great! As long as we don’t have to test any other classes that use the other constructor.
  • 48.
  • 49. Avoid Digging into Collaborators • Pass in the specific object(s) you need • Avoid using “Context” or “Manager” objects to access additional dependencies • Violates Law of Demeter: Context.SomeItem.Foo() • Suspicious Names: environment, principal, container • Symptoms:Tests have mocks that return mocks
  • 50.
  • 51.
  • 52. Avoid Global State Access • Singletons • Static fields or methods • Static initializers • Registries • Service Locators
  • 53. Singletons • Avoid classes that implement their own lifetime tracking • GoF Singleton Pattern • It’s OK to have a container manage object lifetime and enforce having only a single instance of a class within your application
  • 54.
  • 55.
  • 58. Summary • Inject Dependencies • Remember “New is glue”. • Keep yourAPIs honest • Remember the Explicit Dependencies Principle.Tell your friends. • Maintain seams and keep coupling loose
  • 59. Thanks! • Questions? • Follow me at @ardalis • Check out http://DevIQ.com for more on these topics • Take Pride inYour Code! • References • http://misko.hevery.com/code-reviewers-guide/ • Working Effectively with Legacy Code by Michael Feathers Please use Event Board to fill out a session evaluation.

Editor's Notes

  1. https://twitter.com/hashtag/devintersection https://twitter.com/hashtag/breakdependencies Set low expectations
  2. And specifically, we want fast, automated tests.
  3. Developers like to build things, but often the way they connect parts of an application together (if there even are separate parts) is like using super glue. Good luck testing the interface of one building block.
  4. If you haven’t seen it yet, you should. This guy wants to use krazy glue to keep anything from changing. Probably not how we want our software to be designed.
  5. I want to answer these questions in this session. 1. 2. 3.
  6. …unless the system is difficult to break apart
  7. Avoid names that provide no information: CustomerTests Test1 Test2 Test3
  8. PC (seams) vs. MAC (no seams) PC – Power supply goes bad. Solution: Order new power supply, open case, replace. MAC – Power supply goes bad. Solution: Buy a new Mac.
  9. Because they’re small and fast, you should have a lot of unit tests. They should be the foundation of your testing approach. Integration tests can include tests of services that sit between different layers of your application. Defense in Depth These aren’t the only kinds of tests
  10. Test at the lowest level you can, since that will be the least expensive test to write, run, and maintain.
  11. ReSharper calls any test you run a unit test, regardless of what kind of test it actually is.
  12. Also, they shouldn’t be terribly complex, slow, or involve more than one or two classes.
  13. Dependencies are transitive. If A depends on B and B depends on C, then A depends on C. When I talk about breaking dependencies, I’m also talking about reducing coupling. Loosely coupled code can be tested more easily, since there are fewer connections to have to break apart, and they’re easier to swap out.
  14. This can be difficult to test, especially if either of the two classes in question are difficult to set up in a particular state. To fix this, move the behavior where it belongs.
  15. This can of course be refactored further to eliminate the conditional complexity, using inheritance or a compositional pattern.
  16. “Well, the code is more like guidelines than rules.” Assume as little as possible about collaborators’ collaborators Law of Demeter is not just about having two many dots in an expression.
  17. Imagine when you order a pizza, the delivery person uses code like this to get paid. Does this seem to model how things actually work? Should the delivery person have access to your wallet and its contents? What if you don’t have a wallet? This code is now tightly coupled not only to a Customer, but to a Wallet and its implementation.
  18. What if instead the Customer could respond to requests for payment, like this? Note that wallet is no longer exposed outside of the Customer class.
  19. At this point, the original code makes a bit more sense. Payment is requested, and how it is achieved is no longer a concern of the calling code. Payment can come from a money clip, purse, or from under a mattress and this code will still work. Testing this code could use a simplified fake customer and wouldn’t require implementation of both a fake customer and a fake wallet, making test code simpler. Reduce coupling – keep your classes from having to know too much about the details of their collaborators.
  20. Drink water
  21. Constructors should be extremely simple. They shouldn’t choose the object’s collaborators, or how the object is retrieved from persistence. These things violate the Single Responsibility Principle for the constructor’s class, and tightly couple the class to certain implementation details. Constructors that accept collaborators provide seams – hard-coding collaborators erases such seams. New is probably OK for initializing simple things like strings, datetimes, or collections to avoid nulls. Prefer the new C# 6 syntax for this with properties.
  22. Note, it’s fine to create simple types and value objects – simply consider whether it’s making the object harder to test or not when deciding.
  23. This code is difficult to test and tightly coupled to a dbContext, which in this case probably makes it impossible to test this code without a database.
  24. Note that in this case the only thing the constructor does is assign parameters to fields, and no fields are instantiated as part of their declaration.
  25. Likewise, avoid making static lookup calls or assignments within a constructor, especially ones that depend on infrastructure or the local environment. Avoid depending on configuration directly – remember it’s a dependency.
  26. The solution is the same – avoid creating things in the constructor in favor of passing these things in. If you can’t pass in the thing itself, pass in a means of getting to it (like we’re doing with IConfig in this case), but keep it simple as possible.
  27. Dependency injection again saves the day. The initialization logic is a separate responsibility from whatever the service does, and so belongs in another class.
  28. Adds coupling in an invisible, hard to track manner. Makes testing difficult, especially parallel testing or testing in any order Causes Spooky Action at a Distance – your method causes some unexpected behavior in some other part of the system
  29. Third party library with static call
  30. Use a wrapper and inject