CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

January 2006 - Posts

  • I thought you said NOT to cross the streams!

    We had a little snafu at work today from a lack of communication.  It didn't end up costing us any significant amount of time, but it could have.  We had two pairs (all the developers in the office) working on different tasks in essentially the same area of the code base.   My pair was adding functionality to a new class.  The other pair decided that the role of the same class should be different and moved it to a completely different project.  We got out of it pretty quickly by splitting the class into two, but that would have been a nasty merge if we hadn't caught it quickly.  Just like in Ghostbusters, crossing the streams of coding activity is a way to get a priority user story done fast, but it comes with some risk. 

    We knew they were working in code very close to us and we should have told them we were working with that class, and they most definitely should have said something to us before they moved the class to the other project.  My resolution for tomorrow morning is to make sure we all know what the separate pairs are doing until we can get the coding streams isolated from each other.

    I think the danger of pairs stepping all over each other goes down quite a bit as a code base matures.  Early on in a project the roles of classes and the project structure can vary wildly.  I certainly try to keep parallel coding streams separated as much as possible early in a project.  Of course you often don't have much of a choice, so you've just got to be talking much more often and when in doubt, broadcast any breaking changes to the rest of the room.  My preferred coding style is definitely heads down, but in the early stages of a project you just can't afford that attitude.  I think it's awfully important to get the team in front of a whiteboard several times a day until the technical direction emerges and stabilizes.

    Here's another lesson that we relearned today, but in a positive way.  Take Continuous Integration to heart.  It's more than just configuring CruiseControl.Net, it's an attitude.  We got away with working in the same area of the code today precisely because we were checking new code in at least every hour.  We were able to reign in the areas where we were diverging rapidly because we were getting constant feedback on our code from the automated builds.  Try to break the work into smaller chunks so you can check in code frequently.  Frequent, granular check-in's and updates keep the burden of merging to a minimum.  Collective code ownership means paying attention to what the other developers are doing too.  Put another way, big check-in's usually hurt -- and big check-in's at 4:45 in the afternoon are hazardous to your health.  Another reason to keep your automated build as lean and fast as possible is to enable frequent check-in's.

    Stale code gets moldy fast.  One of the worst mini-blunders in my career was not intervening or rotating someone else into a pair that was struggling with a complex WinForms navigation task.  They kept the code out for four days while the main codeline was changing rapidly around them.  When the rest of us finally did get involved we compounded the mistake by not throwing the code away and starting over.  It took two more days to get the code changes merged in, and another day to refactor that code to where we wanted to go in the first place.  All that effort for a story that had been originally estimated at only a half-day to begin with.

    Agile processes make a very conscious decision to maximize the communication between team members as a means of eliminating much of the paperwork typical of formal processes.  For this very reason, Agile teams typically work in open team rooms.  I just can't imagine going back to all of us working in isolated cubicles.  I know Joel Spolsky thinks developers do best when they're working in quiet isolated offices, but I think that's a matter of localized optimization.  This is a reminder to self -- It might optimize the individual coding productivity over the short term, but it'll probably hurt in the long run with nasty integration problems and an alarming degree of code duplication.

  • How big is a User Story?

    I’ve had 3-4 different conversations this week on the proper size of a user story.  My opinion is to simply slice your user stories into the smallest chunks of work that are still:

     

    A.)  Testable

    B.)   Provide some sort of real business value

     

    By testable I mean that there is something that a tester could actually test.  As an example, think about a typical dynamic website application that displays a status report of some kind.  You can’t really write a user story for “fetch data” without the data display because it provides no business value.  You could, however, divide the reporting screen into smaller user stories like:

    1. Query by state
    2. Query by zipcode
    3. Sort the results
    4. Export the results to Excel (I’ve lost track of the number of times and programming languages I’ve done this with now)
    5. Persist query settings

     

    I think smaller user stories help dramatically in creating a smooth running Agile team.  The smaller (and more detailed) the user story, the more accurate the developer estimates will be.  Management types will be happier because they love the predictability of accurate estimating.  The development team can demonstrate progress more often, and it’s just plain cool to see the story cards moving on the story wall.

     

    A highly desirable ability of any team doing iterative development is the ability to produce production ready code at the end of each iteration.   Another related goal is to never carry a nontrivial defect across iteration boundaries.  The only possible way you can arrive at production ready code at the end of the iteration is to get the testers something to test as early as possible in the iteration.  Something I learned the hard way is that you cannot dump the full iteration’s code onto the testers on the last day of the iteration.  If you can break your user stories into smaller units of work you’ll be able to smooth out the workload of the testers more evenly across the duration of the iteration.  A useful thing to watch is the number of stories that are done (coded, tested, and customer approved) at the midpoint of the iteration.  Ideally you want to be halfway done with the iteration stories spread smoothly between the actively coding, testing, and done columns.

     

    One of the major advantages of Agile development in my mind is the way that the workload is more evenly spread out in a sustainable pace.  We don't have much in the way of crunch time, but we also rarely have any downtime.  When I worked in a waterfall shop I remember being constantly frustrated at the cycling between being overworked at the end of a project and underutilized and bored between development cycles.

     

    My team isn’t at this point yet, but we made some very significant changes this past week (plus finally added an onsite tester) that I think will help us get there.  More on that later...

  • Darren Hobbs gives Agile Answers

    I thought this was a very good post answering some of the common objections and concerns to TDD from newcomers.  I've heard some variety of every single objection he lists.

    Agile Answers

  • The sage old man is blogging now

    We finally coaxed our colleague, Gary Williams, to start blogging.  One of my main sources of entertainment is now bringing his act to the blogosphere. 

     

    The feed is http://archivedeveloper.blogspot.com/atom.xml

  • Is anybody using StructureMap?

    I'm finally getting very active in creating the next StructureMap release.  Someone had suggested to me that I include a list in the website of some of the places and projects that are using StructureMap in their development.  If you're using StructureMap, or evaluated it and rejected it, could you leave a comment on how you're using it?  I will not list any company names for obvious reasons.

     

    I do refuse to get into a feature war with Spring.Net, Castle, or whatever the Pico/NanoContainer .Net version has become though (ObjectBuilder isn't even on the map yet IMO).  That's always sounded like a great way to not have a life.  All the tools are built on different models for different needs anyway. 

    I know of:

    • My company (obviously) as the configuration for a rules engine component
    • WinForms and web service system for a small insurance company in Wisconsin
    • Fortune 500 manufacturing company
    • A .Net implementation of the Apache Commons library
    • Jeffrey Palermo's EZWeb

    Thanks!

     

  • Leaky Abstractions and the Last Responsible Moment for Design

    If you haven’t read it before, go check out Joel’s Law of Leaky Abstractions.   I bumped into some code in one of our projects last week that is a classic case of a leaky abstraction.  It looked something like this:

     

                public DataTransferObject ProcessTheMessage(Message message)

                {

                      IMessageHandler[] handlers = createHandlersForMessage(message);

                      DataTransferObject dto = new DataTransferObject();

     

                      foreach (IMessageHandler handler in handlers)

                      {

                            // Check for special case

                            if (handler is SpecialMessageHandler)

                            {

                                  // Downcast to the specific MessageHandler

                                  SpecialMessageHandler special = (SpecialMessageHandler) handler;

     

                                  // Check if the message is from our BigClient with special

                                  // "needs" – Our code didn’t do this, but I’ve seen this

                                  // far too frequently

                                  if (message.ClientId = "BigClient")

                                  {

                                        special.SendEmail(message);

                                  }

                                  else

                                  {

                                        special.Audit(message.Header, message.ClientId);

                                  }

                            }

                            else

                            {

                                  handler.Process(message, dto);

                            }

     

                            // Another exception case if the MessageHandler is Security

                            if (handler is SecurityMessageHandler)

                            {

                                  if (!(SecurityMessageHandler).Authorized)

                                  {

                                        dto.Success = false;

                                        break;

                                  }

                            }

                      }

     

                      return dto;

                }

     

    There is a generalized array of IMessageHandler objects that take their turn processing a Message object, or at least that’s the way it started.  At some point the developers needed to code a special case to short circuit the message handling chain if a specific handler was encountered, or a specific client.  For whatever reasons, the developers chose to go outside the convention of the existing IMessageHandler abstraction.  Once the abstraction springs a leak with one exception case, more exception cases are sure to follow rapidly.  A leaky abstraction is a very clear sign that the overall structure and design of an application is succumbing to entropy and heading for its end of life as changes to the system become too risky or costly.

     

     

    Preventing Leaky Abstractions

     

    I’d say that there are a couple different causes of abstractions springing a leak.  System design and architecture has to be socialized throughout the development team to be successful.  I think there is a “this is the way we do this” factor that has to be in place within a development team for any abstraction to truly work.  Developers that don’t understand the purpose and usage of an abstraction will go around it anytime they’re under schedule pressure – i.e. almost always.

     

    The second big cause is abstracting too early.  When you make a design decision too early you are speculating without all the facts.  To some degree I think very experienced developers and architects can accurately predict what will be useful, but it’s still a gamble.  When you reach too far ahead in your architecture you incur a risk of creating unnecessary infrastructure or creating an unnecessary amount of complexity.  It’s taken me a couple of years now but I think I finally buy (most of the way) into the XP idea of YAGNI.  Abstracting too early is acerbated by changes in requirements or priorities.  The facts and understanding of the business process that underpinned your abstraction have changed and the abstracted model is busted.  Wait to introduce the abstraction until it’s necessary or valuable.  More on this subject below.

     

    Architect Hubris and the Siren Call of Metadata-Driven Architectures

     

    One of the biggest, most colossal mistakes a software architect can make is that of hubris.  “Architect Hubris” is the belief that the architect(s) can design and code an application framework upfront that will reduce the remaining development to a mere exercise in configuration.  I came awfully close one time with a workflow system that was almost completely configurable – via no less than 65 database tables!  The “now its just configuration” moment never arrived.  There was always some kind of exception case that didn’t quite fit into the abstracted model.  It’s really too bad that we spent so much time getting the workflow framework upfront instead of just coding what the business asked for in specific.  We delivered what we had to, but there was a lot of wasted effort in architectural infrastructure that provided no real business benefit.

     

    Favor Composition over Inheritance

     

    I think metadata driven design and extensibility mechanisms still has its place, but I use it differently today than I did back then.  Where I extensibility I do it by abstracting at coarse-grained interfaces, not abstract classes.  I then use StructureMap (shameless plug) to configure object graphs.  I never assume anymore that all implementations of an interface can inherit from a single superclass or be described by an identical set of configured metadata.  Read more from Erich Gamma about the “Favor Composition over Inheritance” principle.

     

    The Last Responsible Moment

     

    I got to participate in a panel on TDD in Austin with Mary Poppendieck last fall.  She spent quite a bit of time talking about the value in making decisions at the last responsible moment.  The key is to make decisions as late as you can responsibly wait because that is the point at which you have the most information on which to base the decision.  In software design it means you forgo creating generalized solutions or class structures until you know that they’re justified or necessary. 

     

    Abstracting too early is problematic, but waiting too long to introduce an abstraction is almost as bad.  You either end up living with duplication in the code (bad) or pay a cost in a larger refactoring to introduce an abstraction to remove the duplication.  Continuous design as practiced by Agilists is not another flavor of chaotic “code n’fix.”  It’s design all the time.  You have to be constantly scanning your code and design and looking for code smells creeping in and opportunities to create abstraction that remove duplication or create greater efficiencies.

     

    I’ve worked with some people who interpret Agile development to mean that you never do any design activity outside of coding.  Let me say this as clearly and forcefully as possible, always be thinking ahead!  Consider different abstractions, research design patterns to reduce conditional logic, and look for reoccurring patterns in the code that can be generalized.  Just don’t implement anything more than you have to for the functionality at hand.  Large refactorings shouldn’t sneak up on you.  You should always have a list of possible improvements to your design floating around both in your head and in conversations with your teammates. 

  • Of Spikes and Prototypes

    Len Holgate recently made a good post on the dangers of runaway prototypes.  Len shares a story of letting prototype code cross the line into production code and paying the consequences. 

     

    We’ve all been there.  Many of the worst, most unreliable pieces of code I’m familiar with began their lives as good-looking prototypes that were rushed into production.  Coincidentally, sometime in the next couple of iterations we’ve got a user story in our backlog to analyze a troublesome mission critical component that began as a prototype rushed into production. 

     

    One of my previous employers had such a terrible history of allowing prototype code into production that there was an explicit policy forbidding prototyping.  Needless to say, the policy could not possibly be enforced, but project managers would get very nervous about any prototyping activities.  They relaxed this stance later and just in time for the big CMM adoption.  The new “disciplined” waterfall approach expressly forbade any coding before the design specification was complete and signed off.  The problem is that it is very difficult to do an accurate upfront design and estimate without doing at least some prototyping work to test out design ideas and unfamiliar technologies.  Any estimate or design with unproven assumptions is nothing but a working theory.  Knowing this, teams would use the “it’s just prototype code” loophole to start doing some coding.  Only when the code seemed to taking shape would they retrofit the design specification against the prototype.  They didn’t throw away the prototype code though, and the trouble continued.

     

    My personal feeling, from experience, is that large scale prototypes are an inefficient usage of time.  It’s a more accurate way to do big upfront design, but you’re potentially spending a lot more time upfront with absolutely zero production quality code (client value) to show for your efforts.  This is the exact situation that leads to sloppy prototype code being deployed to production.  When that deadline starts to creep closer the temptation is going to mount to just “clean up” the prototype and push it in.  For that matter, I have an almost pathological distrust of the typical manager’s ability to understand the consequential differences between prototype code and production quality code (or software quality in general).

     

    If you don’t know what to do, Spike!

     

    One of the points I liked from Len’s post was that he codes in one of two modes.  From Len (emphasis mine), “The first is the controlled, mostly test driven, quality focused coding that I do when I know where I'm going and when I know that I want to use the code for something serious.”  When you don’t know where you’re going or if something can work he switches to a prototyping mode where the only goal is to find out where to go or whether or not the destination is even possible.  In Extreme Programming terms, do a Spike.

     

    A couple of my teammates are new to TDD and they often struggle with writing that first unit test or writing code test first in general.  They often end up trying to write the code first so that they can figure out how to write the test.  The tests that get retrofitted to this code are often gnarly because the code isn’t easy to test.  Even worse is the fact that the retrofitted tests rarely provide the same level of test coverage as unit tests written test first.  Writing the code and retrofitting unit tests isn’t an ideal strategy, but just staring blankly at the IDE hoping for sudden inspiration isn’t a winning strategy either.  Switch gears and do something else. 

     

    I’m very comfortable with UML or CRC modeling to explore ideas, but that isn’t always the right or only answer to breaking the “coder’s block” either.  That’s when it’s time to do a spike.  Forget TDD and all the other “dot the ‘i’, cross the ‘t’” coding activities, go off to some code on the side, and just try to solve the coding problem.  At a minimum, try to learn enough to know how to write the real code.  Then, and this is crucial, throw the spike code away (or at least make sure it isn’t inside the main coding trunk).  Now you can switch back to doing TDD and re-write the spike solution in a disciplined manner.  Even if the spike is exactly the way the code is going to end up, re-write it with TDD to make sure.  One of the very real risks and downsides of spikes is that the code written as a result of the spike often has less test coverage because of the temptation to forgo unit tests on something you’ve already done.

     

    Spikes and Project/Iteration Management

     

    Spikes should be relatively short activities with a specific goal, usually to answer a specific design question or to provide a more accurate estimate for a user story.  The (organized) agile projects I’ve been on have always treated largish spikes as user stories that are prioritized and estimated along with the normal user stories.  The difference is that the estimated time for a spike is really a cap, i.e “we will spend no more than 8 ideal hours on the XYZ spike.”

     

    One of the projects I was on a couple of years ago mandated that a different pair wrote the production version of a spike solution, just because some developer (me) was doing the lion’s share of the spikes and architectural refactorings.  I’m still a little undecided about the wisdom and efficiency of that approach, but it definitely spreads the knowledge around. 

     

    It is obviously useful to keep the spike code around.  Our preference now is to just make a quick Subversion branch and do the spike in this code.  That way the code doesn’t “accidentally” land in the main trunk or get lost later.

     

     

     

    Matt Stephens has a somewhat differing opinion on early prototyping versus the XP-style emergent design concept.  I think he’s more than a little bit incoherent and inaccurate anytime he or Doug Rosenberg talks about XP or XP practices.   I just thought I’d add a link with an opposing view (and I’m pretty sure that the picture of the bridge on his page is the famous 360 bridge in Austin about a mile from my office, so he gets some points). 

  • Great Quote from Jeffrey Palermo

    Our laptops at work are a little shy on memory and with Visual Studio w/ReSharper/Sql Server/IIS going all the time the hard drive light basically never goes off.  On top of that, our laptop model has a reputation for hard drive failures.  We've tried to ask our IT guy for RAM upgrades and been told that the upgraded memory would be too expensive, end of story.  Jeffrey finally got fed up this morning and found a pretty reasonable price on 1 gig memory cards at Frye's.  He explained it to me this morning as being like the "Tell, don't ask" principle in code.  I'm just going to go buy the memory now, and tell them about it later when I turn in the expense report.

     

    Well put.

  • Best and Worst Practices for Mock Objects

    Mock objects are like any other tool.  Used one way they’re a huge time saver.  In other cases they can easily create more work and degrade the quality of the testing code.  In this post I’ll try to present some best and worst practices for utilizing mock objects.  Sadly, every “bad” practice described is something I’ve either done or seen done.

     

    This is the third in a planned series of five posts on mock objects:

     

    1. Introduction to Mocks and Stubs
    2. When and Why to use Mocks and Stubs
    3. Best Practices for Mocks (this post)
    4. Constraints and other Mocking Tricks
    5. Attaching Mocks and Stubs with StructureMap (by request)

     

    Mocking Interfaces and Classes outside Your Code

     

    Be careful about mocking or stubbing any interface that is outside your own codebase.  If you don’t truly understand the semantics and proper usage of an interface you don’t have any business mocking that interface in a unit test.  My best advice is to create your own interface to wrap the interaction with the external API classes. 

     

    The best example from my memory was a security subsystem that retrieved security authorization and user information from Active Directory.  We created a class that queried Active Directory directly (with a painful detour through ADAM) and wrote tests that were fully connected.  Technically we could have probably mocked the System.DirectoryServices classes somehow and just verified that we used the correct LDAP query command, but I don’t think it would have added any value.  The reason I think a mock would have been useless is that determining the correct LDAP query string to return the correct results was the majority of the effort.  I can write SQL queries in my sleep and XPath expressions when I’m merely drowsy, but the LDAP query syntax is pretty wacky (and poorly documented in my experience).

     

    Instead of trying to mock the access to Active Directory, create your own coarse-grained interface for retrieving user information that will encapsulate the AD access.  Besides the testability gain, it’ll keep your other security code decoupled from the storage so that you can chuck the Active Directory strategy when your aggravation level gets too high.  This interface is safe to mock.

     

          public interface IUserInformationStore

          {

                UserInformation FindUser(string userName);

                UserInformation[] FindUsersInRole(string roleName);

          }

     

     

    Avoid Mocking Fine-Grained or Chatty Interfaces

     

    Don’t mock fine grained interfaces.  You’ll wear off the skin on your fingertips and the tests will NOT be intention revealing. 

     

    Specifically, do not mock happy, funny ADO.Net (or JDBC for the Java crowd).  Just think of how many different ADO.Net objects and lines of code it takes to make a typical call to the database.   I’ve watched a couple of people try to write unit tests on their data access code by mocking IDbConnection, IDbCommand, and the various IDataParameter objects.  It’s too much effort for too little gain.  My advice is to just test the data access code against the actual database with integration tests.  For the most part I think testing persistence code without the database is a complete waste of time.  I’d make an obvious exception for data access frameworks and code that generates sql commands though.

     

    By all means, mock the database in your unit tests, but do it in the right way.  With the exception of a DataSet (maybe), I don’t think you should ever expose any ADO.Net objects in the public interface that your data access classes expose to the rest of the system.

     

    If you have a chatty interface, see if you can bunch the calls into some sort of coarse parameter object.  Fowler describes this in his Refactoring book as the Introduce Parameter Object refactoring.  As an example, consider the case of testing user interface screen logic in an ASP.Net application.  One of the first things you need to do is isolate as much code as possible from the ASP.Net runtime objects (you can create an HttpContext in a unit test, but it’s the blackest magic).  We can’t mock the Session directly, but we can put an interface in front of the Session to do state management.

     

          public struct SessionConstants

          {

                internal const string SORT_KEY = "Sort";

                internal const string NAME_FILTER_KEY = "NameFilter";

                internal const string PAGE_NUMBER_KEY = "PageNumber";

                internal const string DATASET_KEY = "Data";

          }

     

          public interface ISession

          {

                string GetStringValue(string key);

                void SetStringValue(string key, string sessionValue);

               

                DataSet GetDataSetValue(string key);

                void SetDataSetValue(string key, DataSet data);

          }

     

          public class SessionWrapper : ISession

          {

                private HttpSessionState _session;

     

                public SessionWrapper()

                {

                      _session = HttpContext.Current.Session;

                }

     

                public string GetStringValue(string key)

                {

                      return (string) _session[key];

                }

     

                public void SetStringValue(string key, string sessionValue)

                {

                      _session[key] = sessionValue;

                }

     

                public DataSet GetDataSetValue(string key)

                {

                      return (DataSet) _session[key];

                }

     

                public void SetDataSetValue(string key, DataSet data)

                {

                      _session[key] = data;

                }

          }

     

    We can now test any web page controller class by using a mock object as a substitute for the Session.  The ISession and SessionWrapper pair will definitely make unit testing the web page controller classes easier, but it forces us into a lot of setup calls in the unit tests for each piece of state (page number, sorting expression, user preferences, etc.).  I think it also creates an ugly coupling from the controllers to the storage mechanism and structure.  A better approach in my opinion is to create a coarse grained class to hold the web page state and a new interface for retrieving the state management that completely decouples the actual storage mechanism.

     

          public class PageState

          {

                private string _sort;

                private string _filter;

                private int _pageNumber;

                private DataSet _data;

     

                public PageState(string sort, string filter, int pageNumber, DataSet data)

                {

                      _sort = sort;

                      _filter = filter;

                      _pageNumber = pageNumber;

                      _data = data;

                }

     

                public string Sort

                {

                      get { return _sort; }

                      set { _sort = value; }

                }

     

                public string Filter

                {

                      get { return _filter; }

                      set { _filter = value; }

                }

     

                public int PageNumber

                {

                      get { return _pageNumber; }

                      set { _pageNumber = value; }

                }

     

                public DataSet Data

                {

                      get { return _data; }

                      set { _data = value; }

                }

          }

     

     

          public interface IStateService

          {

                PageState RetrieveState();

                void StoreState(PageState state);

          }

     

    Now all it takes to setup the mock object in a unit test for a controller class is an expectation for the RetrieveState() method and another for the StoreState() method.  The session state for the test can be quickly setup by calling the constructor function on the PageState object.

     

    In a comment to my last post Ayende Rahein pointed out that excessive numbers of fine-grained expectations will make the tests very brittle to changes in the code.  Been there, done that.

     

    How Many Mock Objects in any Given Test?

     

    How many mock objects are too many?  I’ve worked with some people before that felt that there should never be more than 1-2 mock objects involved in any single unit test.  I wouldn’t make a hard and fast rule on the limit, but anything more than 2 or 3 should probably make you question the design.  The class being tested may have too many responsibilities or the method might be too large.  Look for ways to move some of the responsibilities to a new class or method.  Excessive mock calls can often be a sign of poor encapsulation. 

     

    Inline with Jim Shore’s Reflective Design writing, unit tests and mock objects are another means to gather feedback about your code and design.  If you’re having difficulty using a mock object in a unit test, or you’re incurring more setup overhead in your tests than you’d like, it’s frequently a sign that you need to reconsider your class design.  In other words, too much mocking, either in the number of mock objects or the setup code, in any single unit test is a Coding Smell.

     

    Minimizing the number of mock objects necessary for any given unit test is a very effective way of keeping the Cyclomatic Complexity of your classes below an acceptable level.

     

     

    Only Mock your Nearest Neighbor

     

    Ideally you only want to mock the dependencies of the class being tested, not the dependencies of the dependencies.  From hurtful experience, deviating from this practice will create unit test code that is very tightly coupled to the internal implementation of a class’s dependencies.  A common culprit is the diabolical usage of the Singleton pattern (the authors of the GoF book are making a second version that will supposedly have a full section on Singleton abuse).  A frequent usage of a Singleton is to create a Repository object that manages the communication between a client and its backend services.  Since you cannot mock a Singleton (yeah I know you can do some IL magic, but do you really want to?), myself and many other people fall into the trap of attaching a mock for the backend data source classes into the Singleton instance and setting up the expectations on this mock.  Your unit test is basically validating that the calls that the class being unit tested makes to the repository causes another set of calls to a mock object that is standing in for the data service.  If the Singleton is in an unknown state or the internal caching mechanisms of the repository change, you will end up rewriting unit tests.

     

    Since all I really wanted to test in this case was the interaction of a class with the repository class, I’m much better off writing a simpler test that mocks the repository directly.  Then I don’t have to worry about the state or the internals of the concrete implementation of the repository.

     

    As long as you’re aware of the consequences of a Singleton or static members in general, it’s relatively simple to create a repository that doesn’t harm testability.  Here’s a couple of links on this specific issue:

     

     

    Mock the Right Thing

     

    Here’s an example of the single dumbest thing I’ve ever done with mock objects (and also an example of how NOT to do Model View Presenter).  We were building a WinForms application with somewhat complex workflow between the screens.  Each screen had some logic in the Presenter (Controller) class that determined whether or not the screen could be closed, usually by checking if the data on the screen was “dirty.”  To simulate a view with dirty data, we did something like the following:

     

          [TestFixture]

          public class PresenterTester

          {

                [Test]

                public void CloseViewWhenViewIsNotDirty()

                {

                      // Create the mock objects

                      IMock msgBoxMock = new DynamicMock(typeof(IMessageBoxCreator));

                      IMock viewMock = new DynamicMock(typeof(IView));

     

                      // Define the expected interaction

                      msgBoxMock.ExpectNoCall("AskYesNoQuestion", typeof(string), typeof(string));

                     

                      // Setup the view so that the controller will think the screen is dirty

                      viewMock.SetupResult("Name", "Jeremy");

                      viewMock.SetupResult("PhoneNumber", "SOMETHING DIFFERENT TO MAKE THE SCREEN DIRTY");

                      viewMock.SetupResult("Email", "jeremy@somewhere.com");

                      viewMock.SetupResult("State", "TX");

                      viewMock.SetupResult("PostalCode", "78750");

     

                     

                     

                      viewMock.Expect("Close");

     

                      Model model = new Model("Jeremy", "555-555-5555", "jeremy@somewhere.com", "TX", "78750");

     

                      // Create the presenter class with the mock objects

                      Presenter presenter = new Presenter(

                            model,

                            (IView) viewMock.MockInstance,

                            (IMessageBoxCreator) msgBoxMock.MockInstance);

     

                      // Perform the unit of work

                      presenter.Close();

     

                      // Verify the interaction

                      msgBoxMock.Verify();

                      viewMock.Verify();

                }

          }

     

    This is a terrible unit test.  The “dirty” state of the view was tested by comparing the value of each property on the view class compared to the same property on the internal Model member of the Presenter class.  The unit tests setup “clean” or “dirty” states by setting up results for every single property on the IView interface.  In practice this obfuscated the intention of the unit tests and made the unit tests more laborious to write and maintain.  Everytime you added a new field to the screen, all the Presenter unit tests would break. 

     

    In this case, isolate the “dirty” check so it can be tested separately from the screen flow logic.  What I do now is put an IsDirty() method on the view interface.  In the Presenter unit tests I simply setup a value for IsDirty() to easily simulate all of the paths through the code. 

     

                [Test]

                public void CloseViewWhenViewIsNotDirty()

                {

                      // Create the mock objects

                      IMock msgBoxMock = new DynamicMock(typeof(IMessageBoxCreator));

                      IMock viewMock = new DynamicMock(typeof(IView));

     

                      // Define the expected interaction

                      msgBoxMock.ExpectNoCall("AskYesNoQuestion", typeof(string), typeof(string));

     

                      // Very simply set the screen to be in a "clean" state

                      viewMock.ExpectAndReturn("IsDirty", false);

                      viewMock.Expect("Close");

     

                      // Create the presenter class with the mock objects

                      Presenter presenter = new Presenter(

                            (IView) viewMock.MockInstance,

                            (IMessageBoxCreator) msgBoxMock.MockInstance);

     

                      // Perform the unit of work

                      presenter.Close();

     

                      // Verify the interaction

                      _msgBoxMock.Verify();

                      _viewMock.Verify();

                }

     

     Now we’ve got a lot less mock setup and the unit tests will be less brittle and easier to understand because we’ve eliminated a lot of the noise from the view property setup. 

     

    Watch Out When You Mock Abstract Classes

     

    I would urge a certain level of caution in mocking an abstract class or a concrete class.  For best results my advice is to only mock interfaces to avoid unwanted side effects.  It is certainly possible to mock an abstract class, doing that leads to some side effects that effectively negate all of the advantages of a mock object.  Dynamic mock object tools like NMock can only override virtual methods.  This might not be so much a problem in other languages, but with the .Net languages all methods are non-virtual by default.  This means that some of the behavior that you were trying to remove from the test with a mock is still there.  The dynamic mock libraries work by using Reflection.Emit to create a dynamic proxy on the fly for the requested interface or abstract class.  In the case of an abstract class the dynamic mock can only intercept virtual members and even worse, the constructor function of the superclass will probably be exercised.  Here’s an example of mocking an abstract class that’s caused me some grief in the past.

     

          public abstract class ServiceProvider

          {

                public ServiceProvider()

                {

                      // Connect to a web service to cache some data

                }

     

                public abstract void PerformService();

     

                // Cannot be intercepted by a mock object because it's non-virtual

                public DataSet LookupData(string id)

                {

                      return new DataSet();

                }

          }

     

     

          [TestFixture]

          public class MockExampleTestFixture

          {

                [Test]

                public void TestSomething()

                {

                      // As soon as this code is executed the constructor function of

                      // ServiceProvider will be called

                      DynamicMock mock = new DynamicMock(typeof(ServiceProvider));

                }

          }

     

    When you try to create a mock for ServiceProvider the abstract class is trying to access a web service in its constructor function.  If the web service isn’t available, the unit test blows up.  Even with the mock object, your unit test is now using the web service, making an implicit dependency between your unit test and an external resource and effectively eliminating the advantage of using a mock object in the first place.  The solution is might be simple; look for an opportunity to do an Extract Interface refactoring to create an IServiceProvider interface that can be mocked without any side effects.