Increasing Testability With The Adapter Pattern

(Edit: I accidentally originally fat-clicked the publish button in the middle of creating this post. Sorry for the spam in your reader!)

So, you have some code that you can’t change for some reason. Maybe it’s an external library. Maybe it’s a crucial bit of code that too many things are coupled to, and changing it would be a big headache. Regardless of why, it does the work you need to do (for the most part!) but it’s not exposed in a way you like, or a way that fits 100% what you need to do. So how can you still use it? Also, how can you test that you’re using it correctly? Enter: The Adapter Pattern!

 

The basic idea, and then some

So, with the adapter pattern, the general goal is changing one interface to a desired interface. On top of that, this pattern will also help bring testability to your code. If you’re not familiar with TDD/BDD, or just generally unfamiliar with testing your .NET code, here’s some of the things I’ll be using in this post:

  • nUnit – Unit testing framework. You can also use MSTest (comes with Visual Studio).
  • Moq – Mocking framework. Another popular one is RhinoMocks.
  • NuGet – While not shown here, I did use this tool to add NUnit and Moq to the project. If you were thinking of going and downloading nUnit, Moq, etc manually, don’t! Use NuGet.
  • We’ll also briefly touch on the concept of Dependency Injection, although I won’t be using it here with an IoC container (like Ninject or StructureMap).

 

The Problem

For us, we had a base class (from an external library that we couldn’t change) that we had to inherit to make it “plug in” to another system. This base class had 2 main problems for us

  1. It requires a parameter-less constructor (so goodbye clean dependency injection)
  2. It has lots of methods on the base class that we want to use (although their parameters weren’t exactly what we wanted at times)

So, to give an example – the class (in the external library) looks approximately like this:

   1:  public abstract class UnchangeableBaseClass
   2:  {
   3:      public void PerformOperation(string generalOperationName)
   4:      {
   5:          //Magic stuff happens
   6:      }
   7:   
   8:      public abstract void RunMe();
   9:  }

We have a base class we can’t modify. We have to implement RunMe() to tie it into the system. And on this base class, is a function, “PerformOperation”, that we want to take advantage of, but we don’t like passing in a string.

 

Our Code

So, we go to implement our class, so here’s what we end up with:

   1:  public class YourClass : UnchangeableBaseClass
   2:  {
   3:      public override void RunMe()
   4:      {
   5:          PerformOperation("KeepingItReal");
   6:      }
   7:  }

So, what problems are here? Well, it’s untestable, for one. Second, we really don’t like passing in that string.  Let’s try to write a test (and you’ll see how far we don’t get!) (Note: In good TDD fashion, you’d start with trying to write your test, which would help drive your design to testable code. But the goal of this post is to explain the pattern, which I think will be better served in this order. I’m probably wrong.)

   1:  [Test]
   2:  public void WhenRunning_ItShouldPerformOperation()
   3:  {
   4:      var sut = new YourClass();
   5:   
   6:      sut.RunMe();
   7:   
   8:      //Assert....uh...what?
   9:  }

Wow. Didn’t get far there at all! It’s time for…THE ADAPTER PATTERN!

 

Patterns to the Rescue!

Let’s start with what we WANT the code to look like. And by that, I mean let’s define the interface we wish we were consuming. 

   1:  public interface IPerformOperation
   2:  {
   3:      void PerformOperation(Operations operation);
   4:  }
   5:   
   6:  public enum Operations
   7:  {
   8:      KeepingItReal,
   9:      KeepingItMostlyReal,
  10:      MauryPovich
  11:  }

Pretty simple! Now, lets write our actual adapter, with comments to help explain!

   1:  / Our Adapter implements the interface we want to work against.
   2:  // Also, we name our class with "Adapter". When using patterns, this helps
   3:  // the team to work with a common terminology, and to explain complex ideas simply
   4:  public class UnchangeableAdapter : IPerformOperation
   5:  {
   6:      private readonly UnchangeableBaseClass _baseClass;
   7:   
   8:      // Since we're translating one interface to another, we're going to have to actually
   9:      // have a reference to the class that implements the original interface
  10:      public UnchangeableAdapter(UnchangeableBaseClass baseClass)
  11:      {
  12:          _baseClass = baseClass;
  13:      }
  14:   
  15:      // This is our implementation of our new interface. It simply
  16:      // acts as a pass-through to the original version, along with translating our parameters
  17:      public void PerformOperation(Operations operation)
  18:      {
  19:          _baseClass.PerformOperation(operation.ToString());
  20:      }
  21:  }

Alright, now we’re getting somewhere! Lets get back to that test – I bet we can get somewhere now, with the help of Moq!

   1:  [Test]
   2:  public void WhenRunning_ItShouldPerformOperation()
   3:  {
   4:      // Moq simply asks for what interface we wished our object used
   5:      var operationPerformerMock = new Mock<IPerformOperation>();
   6:   
   7:      // Now, due to the parameter-less constructor constraint, we'll have to do something
   8:      // interesting in our implementation, but we need this for testing. There's multiple
   9:      // ways we could deal with this problem, but the one I use involves multiple constructors
  10:      var sut = new YourClass(operationPerformerMock.Object);
  11:   
  12:      // Oh, and "sut" means "System Under Test" :)
  13:      sut.RunMe();
  14:   
  15:      // This Moq command verifies that our class (YourClass) calls the PerformOperation method on the interface
  16:      // properly. We don't care about the parameter at this point.
  17:      operationPerformerMock.Verify(o => o.PerformOperation(It.IsAny<Operations>()));
  18:  }

Sweet! Now we have a failing test (and not compiling, actually – we don’t have that constructor!). So what now?

Finishing our class

We’re almost there! Home stretch!

   1:  public class YourClass : UnchangeableBaseClass
   2:  {
   3:      private readonly IPerformOperation _operationPerformer;
   4:   
   5:      // Our parameter-less constructor, as needed by the other system.
   6:      public YourClass()
   7:      {
   8:          // Here, we get our concrete adapter. This example is trivial,
   9:          // so nothing more is required, but if you're interested in better
  10:          // software design, I'd recommend checking out the Factory pattern 
  11:          // and Inversion of Control libraries, like Ninject or StructureMap!
  12:          _operationPerformer = new UnchangeableAdapter(this);
  13:      }
  14:   
  15:      // We expose this constructor to allow for testing!
  16:      public YourClass(IPerformOperation operationPerformer)
  17:      {
  18:          _operationPerformer = operationPerformer;
  19:      }
  20:   
  21:      public override void RunMe()
  22:      {
  23:          // Let's simple call the function on our interface!
  24:          _operationPerformer.PerformOperation(Operations.KeepingItReal);
  25:      }
  26:  }

Nice! Let’s run our test…and it passed! Thanks to the adapter pattern, we can now interact with an interface that matches our needs, and gives us the testability we desire in our software.

 

Interested in more?

Want to check out this sample yourself? Head over to gitHub!

If you want more information on design patterns, I cannot recommend the Head First Design Patterns book enough. It’s the best down-to-earth book, to really help you learn not only the pattern, but help identify when to apply them. It’s like “Design Patterns for Dummies” – hell, if I can understand it, anyone can!

Designed by Posicionamiento Web | Bloggerized by GosuBlogger