Here's the Subversion info for the online music app I keep referring to sporadically as Flamingo: svn://208.109.223.228/Suvius.Flamingo.

A couple of notes on the project structure:

  • The initial solution was created by TreeSurgeon, whose cause was recently taken up by Bil Simser
  • The build file was subsequently modified to account for the fact that TreeSurgeon's NAnt file doesn't work for .NET 2.0 solutions. It was borrowed heavily from various demos by JP. I've removed the deploy dependency from the "all" target because there is nothing to deploy yet. Have also add an <nunit2report> task because for the most part, Hillbillies don't like to read XML natively.
  • I'm using Rhino Mocks 3.1 which is where the funky new mockery.Record( ) functionality comes in.

So download the code and follow along with my professional development and we can explore the various definitions of the word "mock". Keep in mind that this series of posts differs from other demos in that it isn't a demo. It's a record of my learning shiny new things. By no means am I suggesting what I'm doing is a de facto standard or even a smart way of doing things. Quite the contrary, I encourage you to call me out if something doesn't look right.

The astute reader will probably guess that I have just finished reading Jimmy Nilsson's Applied Domain Driven Design and Patterns. Well, you'd be wrong. I'm still a couple of chapters from the end.

With that, let's get started. The solution contains two projects: Domain.Test and Domain. Like all the hot shot TDDers I'm trying to emulate, I started with a test:

[ Test ]
public void ShouldBeAbleToRetrieveSongsByAnArtist( )
{
    string artist = "Frank Crummitt";
    int numberOfCrummittSongs = songRepository.GetSongsByArtist( artist ).Count;
    MockRepository mockery = new MockRepository( );
    using ( mockery.Record( ) )
    {
        ISong fakeSong = mockery.DynamicMock<ISong>( );
        SetupResult.For( fakeSong.Artist ).Return( artist );
        songRepository.AddSong( fakeSong );
    }

    Assert.AreEqual( numberOfCrummittSongs + 1, 
songRepository.GetSongsByArtist( artist ).Count ); }

This led to the ISong interface and the SongRepository class, both of which are in the Domain project and neither of which I think belong there. ISong probably should go in a separate Domain.Interfaces project. SongRepository...well, I haven't decided yet.

Pay no notice if the Song class. It shouldn't be there yet because there is no code testing it (which you can verify by executing the "coverage" target in the build file). I've added it because I keep forgetting the API for the UltraID3 library and I left some sample code in the Song's constructor as a reminder.

Incidentally, in case it's not readily obvious, I'm starting with the requirement: Should be able to retrieve songs by an artist.

Some comments on the process to date. Firstly, it's not as easy as it looks coming up with initial tests. It's odd that I've written a test about song objects and still don't need a Song class. Even as I look at the test I've written, I'm wondering if there shouldn't be another to test SongRepository.AddSong.

Secondly, after reading what Nilsson had to go through to create fake objects in his book, I have an even greater appreciation of Rhino Mocks. Here's hoping Oren Eini doesn't get hit by a bus.

But overall, I'm happy with how things have started out. It took a bit to understand the build files I pilfered from JP enough to make my own changes to it but it's effort that translates directly to time saved on future projects.

Kyle the Initialized