Objects have dependencies. Methods don’t

For more counter-intuitive banter, subscribe to my feed:  http://feeds.feedburner.com/jeffreypalermo

There is quite a bit of talk lately about unit testing using the extract method and override, or “inherit & override” method for stubbing out a method for unit testing.  Methods don’t have dependencies, and methods aren’t dependencies.

Objects are dependencies, and object have dependencies.  One object will depend on another object.  Objects are cohesive and present a contract of behavior so other objects know what behavior they can reliably leverage.  Because an object is cohesive, everything necessary to perform all its behavior can be passed into the object’s constructor at the beginning of the object’s life.  Then, that object can perform all of the operations.

In order to test a particular object, I might have to pass some fake objects (stubs, mocks, etc) into the constructor, but the object under test doesn’t care as long as the type is satisfied.  If I can’t test an object by passing in fakes to the constructor (and I can compromise sometimes by using setter injection), then the object is less than cohesive, and I should search the design of the object for an extra concern that is trying to get out.  Once I find the extra concern, I would separate the concern (separation of concerns) into its own object and have than as an explicit dependency by requiring it be passed into the constructor (dependency injection).

Michael Feathers outlines this extract method and override testing technique in his book, “Working Effectively with Legacy Code”, and I’ve used the technique many times to break nasty dependencies on legacy code in order to get it under test.  This is necessary because legacy code can’t be safely refactored until it has a safety net of test coverage.

If your unit test has to know that another method on the same object is being called, then the unit test knows too much about the implementation of the object.  The unit test should be doing black box testing on the object under test.  In other words, the unit test shouldn’t care about what code is written or if 1 method or 10,000 methods inside the object are actually called.  The unit test merely sets up explicit object dependencies and test state, interaction or both.

Thought-provoking “architecture” Austin .Net User Group meeting tonight

For more information about the Austin .Net and Agile community, subscribe to my feed:  http://feeds.feedburner.com/jeffreypalermo

I just got back from an Austin .Net User Group meeting, and instead of a presentation, we had a group discussion on architecture.  We discussed what architecture is, how specific it should be, whether a separate architecture team works, etc.  We saw some react violently against past experiences with bad architects and other voice the strong need for an architect to provide leadership and technical guidance to a development team.

The discussion turned to business with architectural decisions like how “safe” to be with redundant systems and graceful failover.  More ROI decisions.  Elaine Krause pulled the discussion back to development, and we talked a bit about buy vs. build decisions like using tools such as CodeSmith, NetTiers, CSLA, and NHibernate. I couldn’t resist giving a plug that I teach NHibernate in my Agile Boot Camp course.  

Overall, we really didn’t get to a definition of “architecture”.  What else is new.  Other forums have tackled the subject and have only been able to give it a rough definition.  The software context of architecture makes it different in each scenario. 

The following notable people were at the Austin .Net User Group meeting last night:  Blake Caraway, Eric Hexter, Jimmy Bogard, Chad Myers, Jeremy Miller, Eric Anderson, Chris Koenig, and Cy Huckaba.

If you were there and want to be listed, get a blog, and send me the link. 

ASP.NET MVC Framework big changes since Dec CTP

 For more stuff on ASP.NET MVC, subscribe to my feed:  http://feeds.feedburner.com/jeffreypalermo

If you installed the December CTP of the ASP.NET MVC Framework, you had to install it.  The assembly was registered with the GAC, and you didn’t have to deploy the assembly.  The original plan was to release the MVC Framework with a service pack of .Net 3.5.  That is no longer the plan.

In the March CTP, System.Web.Mvc.dl, System.Web.Routing.dll, and System.Web.Abstractions.dll can all be deployed to the bin folder.  They don’t require the GAC.  I like that a lot.  I recently deployed www.partywithpalermo.com using the March CTP drop of the MVC Framework.  I have .Net 3.5 on the web server, and it was super simple. 

Routing is a bit different.   Make sure to change [controller]/[route] to {controller}/{route}.  Minor change.  Overall, I’m actually using to using {} for tokens because of all the NAnt build work I’ve done (NAnt uses ${prperty}).

Routing can be used with existing apps.   If you have every done url rewriting (I have), you know how painful it can be.  Now that routing is in a separate assembly, you can use it with any ASP.NET app you wish.  I really like that concept because routing doesn’t care if you are using the mvc handler or page hander.  It works for parsing urls either way.

Overall, I’m pretty impressed with this CTP (and it is a CTP).  It is not done yet, and Microsoft makes no claims that it is complete.  It’s the second public drop of a new, fledgling framework.  The core, in my opinion, is the routes, controllers, and handoff to the views.   All the other stuff is ancillary.  Once the core is there, libraries like MvcContrib can start adding on extra features.  For instance, I’m looking at leveraging the presentation object validators from the Castle project along with the [DataBind] attribute.  It shouldn’t be to hard to leverage the Castle project here, even while using a different controller base class.  I think they are quite complimentary, and Monorail has so many great features, I don’t think I’ll use the MVC Framework bare. 

Let me know in a comment if you are interested in me releasing the source for www.partywithpalermo.com

RSVP now for Party with Palermo, MVP Summit 2008 edition

Party with Palermo

This party happens to be the day before the MVP Summit and 5 days before the Alt.Net Conference in Seattle.  All are welcome.  Subscribe to my feed to ensure you don’t miss important announcements:  http://feeds.feedburner.com/jeffreypalermo.

 

http://mvpsummit2008.partywithpalermo.com/

 

April 13, 2008 @ 7:00PM – 10:00PM

Jillian’s: http://www.jilliansbilliards.com/
731 Westlake Ave N, Seattle, EA
Ph: 206-223-0300
Cover charge is 1 business card.  This will get you in the door and register you for the grand prize drawings.ize dra

  • Free to attend
  • Free fingerfood
  • Free drink
  • Free swag

 

Contact me if you are interested in being a sponsor.

Current sponsors:

 

This is how ASP.NET MVC controller actions should be unit tested

I’m upgrading my partywithpalermo.com website for the MVP Summit party, and I’m retrofitting my tests to use the March CTP of the MVC Framework.  I have the following action that I need to unit test:

public class MainController : ControllerBase
{
    private readonly IAttendeesRepository _repository;
 
    public MainController(IAttendeesRepository repository, IViewEngine viewEngine)
    {
        _repository = repository;
        ViewEngine = viewEngine;
    }
 
 
    public void Register(string name, string website, string comment)
    {
        var attendee = new Attendee(name, website, comment);
        _repository.SaveNewAttendee(attendee);
        RenderView("confirm", attendee);
    }
}

 

Note the explicit dependencies on IAttendeeRepository and IViewEngine.  That means that I’ll be interacting with those two dependencies in this controller.  Here is my unit test (this passes, by the way):

 

[Test]
public void ShouldSaveAttendee()
{
    var repository = new FakeRepository();
 
    var mockViewEngine = new MockViewEngine();
    var controller = new MainController(repository, mockViewEngine);
    controller.ControllerContext = new ControllerContext(new RequestContext(new HttpContextStub(), new RouteData()), controller);
    controller.Register("Jeffrey.',", "http://www.jeffreypalermo.com?=&@%20", "this comment!?,'.");
 
    Attendee attendee = repository.SavedAttendee;
    Assert.That(attendee.Name, Is.EqualTo("Jeffrey.',"));
    Assert.That(attendee.Website, Is.EqualTo("http://www.jeffreypalermo.com?=&@%20"));
    Assert.That(attendee.Comment, Is.EqualTo("this comment!?,'."));
 
    Assert.That(mockViewEngine.ActualViewContext.ViewName, Is.EqualTo("confirm"));
    Assert.That(mockViewEngine.ActualViewContext.ViewData, Is.EqualTo(attendee));
}
 
private class HttpContextStub : HttpContextBase
{
 
}

 

This is a pretty straightforward unit test except for the line before calling the Register() method.  I have to use setter-injection to set a stubbed ControllerContext.  If I don’t, the Register() method will bomb with an exception when the ViewContext is created, and the code tries to get an HttpContextBase off of the ControllerContext.  It’ll throw a NullReferenceException.  My code doesn’t really care about the ControllerContext or what is in it, but because of how the code is structured, I must use setter injection to break this dependency.  Note that testability is next up on the list of things to do for the MVC Framework team.

Preview2 (March CTP) was all about getting the routing engine out into its own assembly so that it can be used separate from MVC controllers.  Also, the MVC Framework is “binnable”.  You can xcopy deploy it.  There is plenty of time to fix these things, and the team is working on it.  You can also be sure that I’ll keep raising the issue because I’ve been test-driving code for three years, and it’s instinct now to see what is easy and frictionless and separate it from code that is harder to test than it should be.  Overall, pretty good for a CTP.

 

The following is what I would like to write.  The following is how I would like my test to look.  Notice just the absence of the ControllerContext line.

[TestFixture]
public class MainControllerTester
{
    [Test]
    public void ShouldSaveAttendee()
    {
        var repository = new FakeRepository();
 
        var mockViewEngine = new MockViewEngine();
        var controller = new MainController(repository, mockViewEngine);
        controller.Register("Jeffrey", "http://www.jeffreypalermo.com", "this comment");
 
        Attendee attendee = repository.SavedAttendee;
        Assert.That(attendee.Name, Is.EqualTo("Jeffrey"));
        Assert.That(attendee.Website, Is.EqualTo("http://www.jeffreypalermo.com"));
        Assert.That(attendee.Comment, Is.EqualTo("this comment"));
 
        Assert.That(mockViewEngine.ActualViewContext.ViewName, Is.EqualTo("confirm"));
        Assert.That(mockViewEngine.ActualViewContext.ViewData, Is.EqualTo(attendee));
    }
 
    private class MockViewEngine : IViewEngine
    {
        public ViewContext ActualViewContext;
 
        public void RenderView(ViewContext viewContext)
        {
            ActualViewContext = viewContext;
        }
    }
 
    private class FakeRepository : IAttendeesRepository
    {
        public Attendee SavedAttendee;
 
        public IEnumerable<Attendee> GetAttendees()
        {
            throw new NotImplementedException();
        }
 
        public void SaveNewAttendee(Attendee attendee)
        {
            SavedAttendee = attendee;
        }
    }
}

 

Note that my unit test is concerned with explicit dependencies and doesn’t know or care that I’m making use of a PROTECTED method named “RenderView” inside my action.  That detail doesn’t matter because the interaction with the IViewEngine is what is important. 

I also understand that I could use the Legacy code pattern of “Extract and Override Call” (Feathers, p348).  Microsoft has already provided the extracted method, RenderView.  I can override the call to break the dependency, but that pattern is meant to be used as a dependency-breaking technique with legacy code.  If you haven’t read Michael Feathers’ book, Working Effectively with Legacy Code, you should order it right now.  It talks about all kinds of dependency-breaking techniques in order to write unit tests on existing code.  My goal in providing feedback to the MVC Framework team (and I provide feedback, believe me) is to have this framework be something that I would want to use.  There is plenty of time to make the necessary changes, and the team is working hard.

I revised this post a bit after chatting on the phone with Scott Guthrie this evening.  We’ll see some testability improvements in the next drop, and the team is aiming to make drops around every 6 weeks or so.

Note:  I’m playing around with using “var” for locals.  Not sure if I like it yet.  We’ll see.  No need to comment on the “vars”.  Comment on controllers, actions, and unit tests.

New drop of ASP.NET MVC Framework now available

My RSS feed:  http://feeds.feedburner.com/jeffreypalermo

You can download it here.  It’s public and announced at the MIX conference.  A new release of the ASP.NET MVC Framework.  The license allows  you go “go live” and use it in production.  You’ll have to uninstall the December CTP first.  The new install will only drop the assemblies in C:Program FilesMicrosoft ASP.NET MVC Preview 2Assemblies, and then you’ll have to copy them over to your application and drop them in the “bin” folder.

We’ll be upgrading MvcContrib and CodeCampServer to work with the new bits soon.

From looking at the bits, here are some notable changes:

  • Constructor of Route now takes more information (GOOD)
  • There are IDictionary arguments for many things, and that is a GOOD thing.  Before anonymous types were required.
    I like the way Monorail handles this by allowing querystring syntax like: RedirectToAction(“foo”, new string[] {“orderid=” + theOrder.Id});
  • [ControllerAction] is gone.  Public methods are actions by default. (GOOD)
  • RenderView() methods are still protected and only 1 of them is virtual (would like IViewEngine to be used more explicitly)
  • 6 (SIX) members of the Controller class are still marked internal (I’d like to be able to extend them)
  • RouteValueDictionary is just a wrapper for the anonymous type.  (I think we can work towards a better API)
  • Seven properties don’t have setters, such as IPrincipal User {get;} (I’d like to see setters)
  • I still see SEALED classes.  In an extensible framework, sealed is your enemy (I’ll be making not of the sealed classes I’d like to extend)
  • ViewContext is not usable in unit test scenario because of its dependency on HttpContextBase. (It can be refactored to help testability)
    Still can’t mock out the IViewEngine’s RenderView method and have it work in a unit test.  I’m told the team is tackling this next.
  • ComponentController is a welcome addition to enable nested controllers, but, sadly, non of the members are virtual.
  • Lots of view helpers (GOOD)
  • Routing is a separate assembly (GOOD)
  • System.Web.Mvc.dll can be deployed in the bin instead of the GAC (GOOD)
  • We can go live with this drop (and it appears to me to be stable enough for small applications)
  • The team is committed to roughtly 6 weeks in between drops (GOOD).  Release early.  Release often.

Two more people to pay attention to

RSS feed:  http://feeds.feedburner.com/jeffreypalermo

Jimmy Bogard:  Jimmy works for me at Headspring Systems as a senior consultant.  He brings quite a bit of agile knowledge to the table, and he is a leader in the Austin community.  He presented at the last Austin Code Camp, and he is currently leading a book club on Eric Evans’ Domain-Driven Design book.  He is a committer on the NBehave project, and I could go on.  Check out his latest post about letting the customer drive the iteration demo.

Eric Hexter Eric Hexter is an ASP.NET expert and really understands how to make a web application scale.  Eric and I co-founded the MvcContrib project together, and he is responsible for most of the configuration management including the build and the automated publishing of releases.  Eric also helps lead the Austin .Net User Group as one of the three directors, and he is responsible for the execution of the 2007 Austin Code Camp.