SlideShare a Scribd company logo
1 of 53
Breaking Dependencies
to Allow UnitTesting
Steve Smith
CTO, Falafel Software
@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
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?
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: ClassNameMethodNameShould
• NameTest Method: DoSomethingGivenSomething
• 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
Integration
Tests
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 / Core
Presentation
Layer
Business Layer
Infrastructure
Data Access
UnitTests
Integration
Tests
UITests
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
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
• Instead, try to package data and behavior together
• Keep together things that change together
• Common Closure Principle – Classes that change together are packaged together
public class Rental
{
private Movie _movie;
public decimal GetPrice()
{
if (_movie.IsNewRelease)
{
if (_movie.IsChildrens)
{
return 4;
}
return 5;
}
if (_movie.IsChildrens)
{
return 2;
}
return 3;
}
}
public class Movie
{
public bool IsNewRelease { get; set; }
public bool IsChildrens { get; set; }
public string Title { get; set; }
public decimal GetPrice()
{
if (IsNewRelease)
{
if (IsChildrens)
{
return 4;
}
return 5;
}
if (IsChildrens)
{
return 2;
}
return 3;
}
}
Law of Demeter
• Or “Strong 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
public void GetPaidByCustomer(Customer customer)
{
decimal payment = 12.00;
var wallet = customer.Wallet;
if(wallet.Total > payment)
{
wallet.RemoveMoney(payment);
}
else
{
// come back later to get paid
}
}
public class Customer
{
private Wallet _wallet;
public decimal RequestPayment(decimal amount)
{
if(_wallet != null && _wallet.Total > amount)
{
_wallet.RemoveMoney(amount);
return amount;
}
return 0;
}
}
public void GetPaidByCustomer(Customer customer)
{
decimal payment = 12.00;
decimal amountPaid = customer.RequestPayment(payment);
if(amountPaid == payment)
{
// say thank you and provide a receipt
}
else
{
// come back later to get paid
}
}
http://geek-and-poke.com
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
public class MoviesController : Controller
{
private MovieDBContext _db = new MovieDBContext();
private UserManager _userManager;
public MoviesController()
{
_userManager = new SqlUserManager();
}
}
[Test]
public void TestSomeMethod()
{
var controller = new MoviesController();
// Boom! Cannot create without a database
}
public class MoviesController : Controller
{
private MovieDBContext _db;
private UserManager _userManager;
public MoviesController(MovieDbContext dbContext,
userManager)
{
_db = dbContext;
_userManager = userManager;
}
}
[Test]
public void TestSomeMethod()
{
var controller = new MoviesController(fakeContext,
fakeUserManager);
// continue test here
}
public class HomeController: Controller
{
private User _user;
private string _displayMode;
public HomeController()
{
_user = HttpContext.Current.User;
_displayMode = Config.AppSettings[“dispMode”];
}
}
[Test]
public void TestSomeMethod()
{
var controller = new HomeController();
// Boom! Cannot create an active HttpContext
// Also, how to vary display mode when there is one
// configuration file for the whole test project?
}
public class HomeController: Controller
{
private User _user;
private string _displayMode;
public HomeController(User user, IConfig config)
{
_user = user;
_displayMode = config.DisplayMode;
}
}
[Test]
public void TestSomeMethod()
{
var config = new Config() {DisplayMode=“Landscape”};
var user = new User();
var controller = new HomeController(user,config);
}
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
public class SomeService
{
private IUserRepository _userRepository;
private DnsRecord _dnsRecord;
public SomeService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void Initialize()
{
string ip = Server.GetAvailableIpAddress();
_dnsRecord = DNS.Associate(“SomeService”, ip);
}
}
[Test]
public void TestSomeMethod()
{
// I can construct SomeService, but how do I test it
// when every method depends on Initialize() ?
}
public class SomeService
{
private IUserRepository _userRepository;
private DnsRecord _dnsRecord;
public SomeService(IUserRepository userRepository,
DnsRecord dnsRecord)
{
_userRepository = userRepository;
_dnsRecord = dnsRecord;
}
// initialize code moved to factory
[Test]
public void TestSomeMethod()
{
var service = new SomeService(testRepo,
testDnsRecord);
}
“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.
public class SomeService
{
private IUserRepository _userRepository;
// testable constructor
public SomeService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void SomeService()
{
_userRepository = new EfUserRepository();
}
}
// how can we test this?
public void SomeMethodElsewhere()
{
var result = new SomeService().DoSomething();
}
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
public class TaxCalculator
{
private TaxTable _taxTable;
…
public decimal ComputeTax(User user, Invoice invoice)
{
var address = user.Address;
var amount = invoice.Subtotal;
var rate = _taxTable.GetTaxRate(address);
return amount * rate;
}
}
// tests must now create users and invoices
// instead of just passing in address and subtotal amount
public class TaxCalculator
{
private TaxTable _taxTable;
…
public decimal ComputeTax(Address address,
decimal subtotal)
{
var rate = _taxTable.GetTaxRate(address);
return subtotal * rate;
}
}
// API is now more honest about what it actually requires
// Tests are much simpler to write
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
public class TrainScheduler
{
public Track FindAvailableTrack()
{
// loop through available tracks
if(TrackStatusChecker.IsAvailable(track))
// do something
return track;
}
}
// tests of FindAvailableTrack now depend on
// TrackStatusChecker, which is a slow web service
public class TrainScheduler
{
private TrainStatusCheckerWrapper _wrapper;
TrainScheduler(TrainStatusCheckerWrapper wrapper)
{
_wrapper = wrapper;
}
public Track FindAvailableTrack()
{
// loop through available tracks
if(_wrapper.IsAvailable(track))
// do something
return track;
}
}
// tests of FindAvailableTrack now can easily inject a
// wrapper to test the behavior of FindAvailableTrack()
// wrapper could just as easily be an interface
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

More Related Content

What's hot

Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018Steven Smith
 
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 RussellQA or the Highway
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Dror Helper
 
Battle of The Mocking Frameworks
Battle of The Mocking FrameworksBattle of The Mocking Frameworks
Battle of The Mocking FrameworksDror Helper
 
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 2018Steven Smith
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing SoftwareSteven Smith
 
How To Use Selenium Successfully
How To Use Selenium SuccessfullyHow To Use Selenium Successfully
How To Use Selenium SuccessfullyDave Haeffner
 
The Cowardly Test-o-Phobe's Guide To Testing
The Cowardly Test-o-Phobe's Guide To TestingThe Cowardly Test-o-Phobe's Guide To Testing
The Cowardly Test-o-Phobe's Guide To TestingTim Duckett
 
How to grow your own Microservice?
How to grow your own Microservice?How to grow your own Microservice?
How to grow your own Microservice?Dmitry Buzdin
 
Chegg - iOS @ Scale
Chegg - iOS @ ScaleChegg - iOS @ Scale
Chegg - iOS @ ScaleAviel Lazar
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy CodeExcella
 
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...Ortus Solutions, Corp
 
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.NET Conf UY
 
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...Uma Ghotikar
 
Системный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестовСистемный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестовCOMAQA.BY
 
Как стать синьором
Как стать синьоромКак стать синьором
Как стать синьоромCOMAQA.BY
 
Practical Test Automation Deep Dive
Practical Test Automation Deep DivePractical Test Automation Deep Dive
Practical Test Automation Deep DiveAlan Richardson
 
Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternSargis Sargsyan
 

What's hot (20)

Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
 
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
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
Battle of The Mocking Frameworks
Battle of The Mocking FrameworksBattle of The Mocking Frameworks
Battle of The Mocking Frameworks
 
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
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing Software
 
How To Use Selenium Successfully
How To Use Selenium SuccessfullyHow To Use Selenium Successfully
How To Use Selenium Successfully
 
The Cowardly Test-o-Phobe's Guide To Testing
The Cowardly Test-o-Phobe's Guide To TestingThe Cowardly Test-o-Phobe's Guide To Testing
The Cowardly Test-o-Phobe's Guide To Testing
 
How to grow your own Microservice?
How to grow your own Microservice?How to grow your own Microservice?
How to grow your own Microservice?
 
Chegg - iOS @ Scale
Chegg - iOS @ ScaleChegg - iOS @ Scale
Chegg - iOS @ Scale
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Into...
 
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
 
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
Introduction to Unit Testing, BDD and Mocking using TestBox & MockBox at Adob...
 
Системный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестовСистемный взгляд на параллельный запуск Selenium тестов
Системный взгляд на параллельный запуск Selenium тестов
 
Testable requirements
Testable requirementsTestable requirements
Testable requirements
 
IoC and Mapper in C#
IoC and Mapper in C#IoC and Mapper in C#
IoC and Mapper in C#
 
Как стать синьором
Как стать синьоромКак стать синьором
Как стать синьором
 
Practical Test Automation Deep Dive
Practical Test Automation Deep DivePractical Test Automation Deep Dive
Practical Test Automation Deep Dive
 
Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component Pattern
 

Viewers also liked

Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...
Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...
Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...wepc2016
 
Stephen Geri: What To Keep In Mind When Buying New Clubs
Stephen Geri: What To Keep In Mind When Buying New ClubsStephen Geri: What To Keep In Mind When Buying New Clubs
Stephen Geri: What To Keep In Mind When Buying New ClubsStephen Geri
 
.NET программирование - 1 Введение
.NET программирование - 1 Введение.NET программирование - 1 Введение
.NET программирование - 1 ВведениеAlexander Morozov
 
Aprendizaje autónomo héctor rosales
Aprendizaje autónomo héctor rosalesAprendizaje autónomo héctor rosales
Aprendizaje autónomo héctor rosaleshectorrosales1980
 
Implementing Domain Event with Akka
Implementing Domain Event with AkkaImplementing Domain Event with Akka
Implementing Domain Event with AkkaTung Nguyen
 
Workshop ferramentas web 2.0
Workshop ferramentas web 2.0Workshop ferramentas web 2.0
Workshop ferramentas web 2.0Paula CAA
 
Tourism measurement - Economical measurements
Tourism measurement - Economical measurementsTourism measurement - Economical measurements
Tourism measurement - Economical measurementsDeenadhayalan Pongiyanan
 
The Brand Journalist's Toolbox
The Brand Journalist's ToolboxThe Brand Journalist's Toolbox
The Brand Journalist's ToolboxProwly PR Software
 
Reaching Production Faster with Containers in Testing
Reaching Production Faster with Containers in TestingReaching Production Faster with Containers in Testing
Reaching Production Faster with Containers in TestingC4Media
 

Viewers also liked (13)

Biodiversity I
Biodiversity IBiodiversity I
Biodiversity I
 
EPSON008.PDF
EPSON008.PDFEPSON008.PDF
EPSON008.PDF
 
Mariela
MarielaMariela
Mariela
 
UK Tamil nadu and Puducherry business meet
UK Tamil nadu and Puducherry business meet UK Tamil nadu and Puducherry business meet
UK Tamil nadu and Puducherry business meet
 
Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...
Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...
Day 1: Innovation in parliaments #1, Mr. Rovil Kumar, Head of IT, Parliament,...
 
Stephen Geri: What To Keep In Mind When Buying New Clubs
Stephen Geri: What To Keep In Mind When Buying New ClubsStephen Geri: What To Keep In Mind When Buying New Clubs
Stephen Geri: What To Keep In Mind When Buying New Clubs
 
.NET программирование - 1 Введение
.NET программирование - 1 Введение.NET программирование - 1 Введение
.NET программирование - 1 Введение
 
Aprendizaje autónomo héctor rosales
Aprendizaje autónomo héctor rosalesAprendizaje autónomo héctor rosales
Aprendizaje autónomo héctor rosales
 
Implementing Domain Event with Akka
Implementing Domain Event with AkkaImplementing Domain Event with Akka
Implementing Domain Event with Akka
 
Workshop ferramentas web 2.0
Workshop ferramentas web 2.0Workshop ferramentas web 2.0
Workshop ferramentas web 2.0
 
Tourism measurement - Economical measurements
Tourism measurement - Economical measurementsTourism measurement - Economical measurements
Tourism measurement - Economical measurements
 
The Brand Journalist's Toolbox
The Brand Journalist's ToolboxThe Brand Journalist's Toolbox
The Brand Journalist's Toolbox
 
Reaching Production Faster with Containers in Testing
Reaching Production Faster with Containers in TestingReaching Production Faster with Containers in Testing
Reaching Production Faster with Containers in Testing
 

Similar to Breaking Dependencies to Allow Unit Testing

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 2014FalafelSoftware
 
How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?Dmitry Buzdin
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFXHendrik Ebbers
 
Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)Oscar Merida
 
Testing the Untestable
Testing the UntestableTesting the Untestable
Testing the UntestableMark Baker
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestSeb Rose
 
Qt test framework
Qt test frameworkQt test framework
Qt test frameworkICS
 
Testcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentationTestcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentationRichard North
 
谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testabilitydrewz lin
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Chris Weldon
 
Some testing - Everything you should know about testing to go with @pedro_g_s...
Some testing - Everything you should know about testing to go with @pedro_g_s...Some testing - Everything you should know about testing to go with @pedro_g_s...
Some testing - Everything you should know about testing to go with @pedro_g_s...Sergio Arroyo
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctlyDror Helper
 
VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)Rob Hale
 
Advance unittest
Advance unittestAdvance unittest
Advance unittestReza Arbabi
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETBen Hall
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchMats Bryntse
 
Level Up Your Integration Testing With Testcontainers
Level Up Your Integration Testing With TestcontainersLevel Up Your Integration Testing With Testcontainers
Level Up Your Integration Testing With TestcontainersVMware Tanzu
 

Similar to Breaking Dependencies to Allow Unit Testing (20)

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
 
How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)
 
Unit tests and TDD
Unit tests and TDDUnit tests and TDD
Unit tests and TDD
 
Testing the Untestable
Testing the UntestableTesting the Untestable
Testing the Untestable
 
Stopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under TestStopping the Rot - Putting Legacy C++ Under Test
Stopping the Rot - Putting Legacy C++ Under Test
 
Qt test framework
Qt test frameworkQt test framework
Qt test framework
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Testcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentationTestcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentation
 
谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability谷歌 Scott-lessons learned in testability
谷歌 Scott-lessons learned in testability
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Some testing - Everything you should know about testing to go with @pedro_g_s...
Some testing - Everything you should know about testing to go with @pedro_g_s...Some testing - Everything you should know about testing to go with @pedro_g_s...
Some testing - Everything you should know about testing to go with @pedro_g_s...
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctly
 
VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)
 
Advance unittest
Advance unittestAdvance unittest
Advance unittest
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NET
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
 
Level Up Your Integration Testing With Testcontainers
Level Up Your Integration Testing With TestcontainersLevel Up Your Integration Testing With Testcontainers
Level Up Your Integration Testing With Testcontainers
 

More from Steven Smith

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 ArdalisSteven Smith
 
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 PatternsSteven Smith
 
Introducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashIntroducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashSteven Smith
 
Most Useful Design Patterns
Most Useful Design PatternsMost Useful Design Patterns
Most Useful Design PatternsSteven Smith
 
Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0Steven Smith
 
Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain EventsSteven Smith
 
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 5Steven Smith
 
My Iraq Experience
My Iraq ExperienceMy Iraq Experience
My Iraq ExperienceSteven Smith
 
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 MVCSteven Smith
 
Refactoring with SOLID Principles (FalafelCon 2013)
Refactoring with SOLID Principles (FalafelCon 2013)Refactoring with SOLID Principles (FalafelCon 2013)
Refactoring with SOLID Principles (FalafelCon 2013)Steven Smith
 
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 2013Steven Smith
 
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 2013Steven Smith
 
Refactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesRefactoring Applications using SOLID Principles
Refactoring Applications using SOLID PrinciplesSteven Smith
 
Common asp.net design patterns aspconf2012
Common asp.net design patterns aspconf2012Common asp.net design patterns aspconf2012
Common asp.net design patterns aspconf2012Steven Smith
 
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)Steven Smith
 
Introducing Pair Programming
Introducing Pair ProgrammingIntroducing Pair Programming
Introducing Pair ProgrammingSteven Smith
 
Cinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patternsCinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patternsSteven Smith
 

More from Steven Smith (18)

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 - 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
 
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
 
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
 
Cinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patternsCinci ug-january2011-anti-patterns
Cinci ug-january2011-anti-patterns
 

Recently uploaded

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 

Recently uploaded (20)

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 

Breaking Dependencies to Allow Unit Testing

  • 1. Breaking Dependencies to Allow UnitTesting Steve Smith CTO, Falafel Software @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. Legacy Code “To me, legacy code is simply code without tests.” Michael Feathers Working Effectively with Legacy Code
  • 7. Hollywood made a whole movie about it…
  • 8. But let’s back up… • Why UnitTests? • Why not just use other kinds of tests? • What are dependencies? • How do we break these dependencies?
  • 9. 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.
  • 10. UnitTests are (should be) FAST • No dependencies means 1000s of tests per second • Run them constantly
  • 11. UnitTests are SMALL • Testing one thing should be simple • If not, can it be made simpler? • Should be quick to write
  • 12. UnitTest Naming • Descriptive And Meaningful Phrases (DAMP) • NameTest Class: ClassNameMethodNameShould • NameTest Method: DoSomethingGivenSomething • http://ardalis.com/unit-test-naming-convention
  • 13. Seams • Represent areas of code where pieces can be decoupled • Testable code has many seams; legacy code has few, if any
  • 15. 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
  • 16. Don’t believe your test runner… IntegrationTest
  • 17. UnitTest? • Requires a database or file? • Sends emails? • Must be executed through the UI? Not a unit test
  • 18. Dependencies and Coupling All dependencies point toward infrastructure Presentation Layer Business Layer Infrastructure Data Access Tests Tests (and everything else) now depend on Infrastructure
  • 19. 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#
  • 20. Depend on Abstractions All dependencies point toward Business Logic / Core Presentation Layer Business Layer Infrastructure Data Access UnitTests Integration Tests UITests
  • 21. 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
  • 22. Common Dependencies to Decouple •Database •File System •Email •Web APIs •System Clock •Configuration •Thread.Sleep •Random
  • 23. 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
  • 24. 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
  • 25. Feature Envy • Characterized by many getter calls • Instead, try to package data and behavior together • Keep together things that change together • Common Closure Principle – Classes that change together are packaged together
  • 26. public class Rental { private Movie _movie; public decimal GetPrice() { if (_movie.IsNewRelease) { if (_movie.IsChildrens) { return 4; } return 5; } if (_movie.IsChildrens) { return 2; } return 3; } }
  • 27. public class Movie { public bool IsNewRelease { get; set; } public bool IsChildrens { get; set; } public string Title { get; set; } public decimal GetPrice() { if (IsNewRelease) { if (IsChildrens) { return 4; } return 5; } if (IsChildrens) { return 2; } return 3; } }
  • 28. Law of Demeter • Or “Strong 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
  • 29. public void GetPaidByCustomer(Customer customer) { decimal payment = 12.00; var wallet = customer.Wallet; if(wallet.Total > payment) { wallet.RemoveMoney(payment); } else { // come back later to get paid } }
  • 30. public class Customer { private Wallet _wallet; public decimal RequestPayment(decimal amount) { if(_wallet != null && _wallet.Total > amount) { _wallet.RemoveMoney(amount); return amount; } return 0; } }
  • 31. public void GetPaidByCustomer(Customer customer) { decimal payment = 12.00; decimal amountPaid = customer.RequestPayment(payment); if(amountPaid == payment) { // say thank you and provide a receipt } else { // come back later to get paid } }
  • 33. 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
  • 34. 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
  • 35. “ ” IoC Containers are just factories on steroids. Don’t be afraid to use them where they can help
  • 36. public class MoviesController : Controller { private MovieDBContext _db = new MovieDBContext(); private UserManager _userManager; public MoviesController() { _userManager = new SqlUserManager(); } } [Test] public void TestSomeMethod() { var controller = new MoviesController(); // Boom! Cannot create without a database }
  • 37. public class MoviesController : Controller { private MovieDBContext _db; private UserManager _userManager; public MoviesController(MovieDbContext dbContext, userManager) { _db = dbContext; _userManager = userManager; } } [Test] public void TestSomeMethod() { var controller = new MoviesController(fakeContext, fakeUserManager); // continue test here }
  • 38. public class HomeController: Controller { private User _user; private string _displayMode; public HomeController() { _user = HttpContext.Current.User; _displayMode = Config.AppSettings[“dispMode”]; } } [Test] public void TestSomeMethod() { var controller = new HomeController(); // Boom! Cannot create an active HttpContext // Also, how to vary display mode when there is one // configuration file for the whole test project? }
  • 39. public class HomeController: Controller { private User _user; private string _displayMode; public HomeController(User user, IConfig config) { _user = user; _displayMode = config.DisplayMode; } } [Test] public void TestSomeMethod() { var config = new Config() {DisplayMode=“Landscape”}; var user = new User(); var controller = new HomeController(user,config); }
  • 40. 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
  • 41. public class SomeService { private IUserRepository _userRepository; private DnsRecord _dnsRecord; public SomeService(IUserRepository userRepository) { _userRepository = userRepository; } public void Initialize() { string ip = Server.GetAvailableIpAddress(); _dnsRecord = DNS.Associate(“SomeService”, ip); } } [Test] public void TestSomeMethod() { // I can construct SomeService, but how do I test it // when every method depends on Initialize() ? }
  • 42. public class SomeService { private IUserRepository _userRepository; private DnsRecord _dnsRecord; public SomeService(IUserRepository userRepository, DnsRecord dnsRecord) { _userRepository = userRepository; _dnsRecord = dnsRecord; } // initialize code moved to factory [Test] public void TestSomeMethod() { var service = new SomeService(testRepo, testDnsRecord); }
  • 43. “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.
  • 44. public class SomeService { private IUserRepository _userRepository; // testable constructor public SomeService(IUserRepository userRepository) { _userRepository = userRepository; } public void SomeService() { _userRepository = new EfUserRepository(); } } // how can we test this? public void SomeMethodElsewhere() { var result = new SomeService().DoSomething(); }
  • 45. 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
  • 46. public class TaxCalculator { private TaxTable _taxTable; … public decimal ComputeTax(User user, Invoice invoice) { var address = user.Address; var amount = invoice.Subtotal; var rate = _taxTable.GetTaxRate(address); return amount * rate; } } // tests must now create users and invoices // instead of just passing in address and subtotal amount
  • 47. public class TaxCalculator { private TaxTable _taxTable; … public decimal ComputeTax(Address address, decimal subtotal) { var rate = _taxTable.GetTaxRate(address); return subtotal * rate; } } // API is now more honest about what it actually requires // Tests are much simpler to write
  • 48. Avoid Global State Access • Singletons • Static fields or methods • Static initializers • Registries • Service Locators
  • 49. 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
  • 50. public class TrainScheduler { public Track FindAvailableTrack() { // loop through available tracks if(TrackStatusChecker.IsAvailable(track)) // do something return track; } } // tests of FindAvailableTrack now depend on // TrackStatusChecker, which is a slow web service
  • 51. public class TrainScheduler { private TrainStatusCheckerWrapper _wrapper; TrainScheduler(TrainStatusCheckerWrapper wrapper) { _wrapper = wrapper; } public Track FindAvailableTrack() { // loop through available tracks if(_wrapper.IsAvailable(track)) // do something return track; } } // tests of FindAvailableTrack now can easily inject a // wrapper to test the behavior of FindAvailableTrack() // wrapper could just as easily be an interface
  • 52. Summary • Inject Dependencies • Remember “New is glue”. • Keep yourAPIs honest • Remember the Explicit Dependencies Principle.Tell your friends. • Maintain seams and keep coupling loose
  • 53. 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

Editor's Notes

  1. https://twitter.com/hashtag/devintersection https://twitter.com/hashtag/breakdependencies
  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. NEED GRAPHIC HERE FOR SEAM – maybe pulling apart two legos, or photo of a carpentry joint
  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
  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.
  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
  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.
  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