Los Techies : Blogs about software and anything tech!

Refactoring Day 12 : Break Dependencies


Today's refactoring is useful if you are trying to introduce unit tests into your code base as testing “seams” are needed to properly mock/isolate areas you don’t wish to test. In this example we have client code that is using a static class to accomplish some work. The problem with this when it comes to unit testing because there is no way to mock the static class from our unit test. To work around this you can apply a wrapper interface around the static to create a seam and break the dependency on the static.

   1: public class AnimalFeedingService
   2: {
   3:     private bool FoodBowlEmpty { get; set; }
   4:  
   5:     public void Feed()
   6:     {
   7:         if (FoodBowlEmpty)
   8:             Feeder.ReplenishFood();
   9:  
  10:         // more code to feed the animal
  11:     }
  12: }
  13:  
  14: public static class Feeder
  15: {
  16:     public static void ReplenishFood()
  17:     {
  18:         // fill up bowl
  19:     }
  20: }

All we did to apply this refactoring was introduce an interface and class that simply calls the underlying static class. So the behavior is still the same, just the manner in which it is invoked has changed. This is good to get a starting point to begin refactoring from and an easy way to add unit tests to your code base.

   1: public class AnimalFeedingService
   2: {
   3:     public IFeederService FeederService { get; set; }
   4:  
   5:     public AnimalFeedingService(IFeederService feederService)
   6:     {
   7:         FeederService = feederService;
   8:     }
   9:  
  10:     private bool FoodBowlEmpty { get; set; }
  11:  
  12:     public void Feed()
  13:     {
  14:         if (FoodBowlEmpty)
  15:             FeederService.ReplenishFood();
  16:  
  17:         // more code to feed the animal
  18:     }
  19: }
  20:  
  21: public interface IFeederService
  22: {
  23:     void ReplenishFood();
  24: }
  25:  
  26: public class FeederService : IFeederService
  27: {
  28:     public void ReplenishFood()
  29:     {
  30:         Feeder.ReplenishFood();
  31:     }
  32: }
  33:  
  34: public static class Feeder
  35: {
  36:     public static void ReplenishFood()
  37:     {
  38:         // fill up bowl
  39:     }
  40: }

We can now mock IFeederService during our unit test via the AnimalFeedingService constructor by passing in a mock of IFeederService. Later we can move the code in the static into FeederService and delete the static class completely once we have some tests in place.

This is part of the 31 Days of Refactoring series. For a full list of Refactorings please see the original introductory post.

Kick It on DotNetKicks.com
Posted Aug 12 2009, 08:15 AM by schambers

Comments

Graham wrote re: Refactoring Day 12 : Break Dependencies
on 08-12-2009 10:27 AM

Watch out for that NRE!

schambers wrote re: Refactoring Day 12 : Break Dependencies
on 08-12-2009 10:32 AM

I'm not sure I follow. If you refactored in this manner, you would use an IoC framework to inject the dependencies via ctor so you wouldn't have a NRE on IFeedService.

Were you referring to somewhere else?

Charris wrote re: Refactoring Day 12 : Break Dependencies
on 08-12-2009 2:28 PM

I guess at least testing for the null ref and throwing?

schambers wrote re: Refactoring Day 12 : Break Dependencies
on 08-12-2009 2:34 PM

Well once you have this wired up with IoC, you will never have a NRE from IFeedService. If you do then your IoC configuration is incorrect and you have larger problems.

I personally to check for NRE's with classes that are registered in IoC. Doesn't seem like theres a point when a instance will always be provided.

Arjan’s World » LINKBLOG for August 13, 2009 wrote Arjan’s World » LINKBLOG for August 13, 2009
on 08-13-2009 11:22 AM

Pingback from  Arjan’s World    » LINKBLOG for August 13, 2009

on 08-13-2009 12:58 PM

Pluralsight On-Demand! I plan to have a full post on Pluralsight On- Demand! very soon. I became a subscriber recently and have found it to be an amazing training tool. Its just ike being in the classroom with the best instructors in the business and

Twitted by ke4ktz wrote Twitted by ke4ktz
on 08-13-2009 6:10 PM

Pingback from  Twitted by ke4ktz

张荣华 wrote 31天重构指南之十二:分解依赖
on 09-29-2009 3:41 AM

如果你要在你的代码中加入单元测试但有一部分代码是你不想测试的,那么你应用使用今天的重构。在下面的例子中我们应用静态类来完成某些工作,但问题是在单元测试时我们无法mock静态类,所以我们只能引入静态类的...

31 Days of Refactoring « Vincent Leung's .NET Tech Clips wrote 31 Days of Refactoring « Vincent Leung's .NET Tech Clips
on 10-28-2009 9:28 AM

Pingback from  31 Days of Refactoring « Vincent Leung's .NET Tech Clips

PetterLiu wrote 31 Days of Refactoring
on 11-27-2009 4:01 AM

Refactoring Day 1 : Encapsulate Collection Refactoring Day 2 : Move Method Refactoring Day 3 : Pull ...

PetterLiu wrote 31 Days of Refactoring
on 11-27-2009 4:03 AM

Refactoring Day 1 : Encapsulate Collection Refactoring Day 2 : Move Method Refactoring Day 3 : Pull ...

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems