Defining interfaces through mocking
February 25th, 2007
This post is a re-work of my Barcamp presentation I did the other day on good OO design though mocking.
Now when I first started doing TDD over six years ago the major thing that struck me was how well designed the interactions between associated objects were compared to applications I’d written in the past without TDD. This was all because by writing test first I was forcing myself to think about how my objects were going to interact with my tests and thus with other objects within the system. Another thing I discovered was also how using mocks even more so allowed me to concentrate even more on the interfaces of the object while developing my models. OK so thats a bit of a lie, back then when I was doing TDD I was doing J2EE development with EJB 2.0 and as we all know this led to anaemic models because all our business logic had to be pulled in via service objects. So no, back then I wasn’t thinking too much about the interfaces of my “models”, more on my service objects;).
I’m going to run through a fairly trivial example just to give you a little taste of what I’m talking about. I’m going to be using RSpec with its built in mocking support in my examples but I could of easily used Test::Unit with Flexmock or Mocha/Stubba.
Step one – Make a cup of tea
Step two – Install the RSpec gem
$ sudo gem install rspec
Step three – Create a Rails application, in this case we’re going to work on a small part of an auction application.
$ rails rspec_auction
$ cd rspec_auction
Setup both your development and test database by editing the database.yml. We won’t actually be hitting the database in the tests but unfortunately you’ll need to set it up.
Step four – Install the RSpec on Rails plugin and generate the helpers and directories that the plugin needs.
$ ruby script/plugin install \
svn://rubyforge.org/var/svn/rspec \
/tags/REL_0_7_5_1/rspec_on_rails/vendor/plugins/rspec_on_rails
$ script/generate rspec
Step five – Make another cup of tea.
Step six – Lets create an Auction model. Now the RSpec plugin for Rails provides you with several generators which will be familiar to you if you’ve used the Rails generators before.
$ script/generate rspec_model auction
Step seven – Hopefully you’ve already got the project open in a text editor or your favourite IDE. We need to make a small alteration the the file spec_helper.rb otherwise we’re going to have problems with Activerecords type checking. Yes, you heard me correctly, I said type checking;). Anyways at the bottom of the spec_helper.rb file you’ll need to add the following lines.
module ActiveRecord
module Associations
class AssociationProxy
def raise_on_type_mismatch(record)
# do nothing
end
end
end
end
Oh and you’ll also need a basic migration file for your auction model so in the file 001_create_auctions.rb that’s already been generated for you add the following:
class CreateAuctions < ActiveRecord::Migration
def self.up
create_table :auctions do |t|
t.column :title, :string
t.column :description, :text
t.column :updated_at, :datetime
t.column :created_at, :datetime
t.column :expires_at, :datetime
t.column :starting_bid, :float
t.column :active, :boolean
end
end
def self.down
drop_table :auctions
end
end
Step eight – OK, now we’re all set to do some coding. Open up the auction_spec.rb file and the first thing you’ll see is something called a context with a description and specifications. When testing our model we may have multiple contexts all depicting the model in different states such as a new auction, an auction about to expire or an auction that has been canceled for example.
In this case the default context generated for us is “Given a generated auction_spec.rb with fixtures loaded”... Not exactly what we’re looking for. So delete this entire context including the specification and replace it with this:
require File.dirname(__FILE__) + '/../spec_helper'
module AuctionSpecHelper
#Valid attributes for an auction
def self.valid_auction_attributes
{
:title => "Big bamboo",
:description => "One caring owner, still in good condition",
:expires_at => 7.days.from_now,
:starting_bid => 0.20,
:active => true
}
end
def self.invalid_auction_attributes
{
:title => nil,
:description => nil,
:expires_at => 7.days.ago,
:starting_bid => "moo",
:active => true
}
end
end
context "A general auction" do
setup do
@auction = Auction.new
end
specify "should have errors given invalid values" do
@auction.attributes = AuctionSpecHelper.invalid_auction_attributes
@auction.valid?.should_equal false
end
specify "should have no errors given valid values" do
@auction.attributes = AuctionSpecHelper.valid_auction_attributes
@auction.valid?.should_equal true
end
end
The module helper at the top of the source should be self explanatory. I’m using it to store hashes of invalid and valid attributes for an auction.
Run the model spec’s by typing the following at the command line:rake spec:models
You’ve probably noticed that I’ve shot ahead and added not one but two specifications. There wouldn’t be much point in the “should have no errors” specification as I haven’t actually written any constraints in the auction model yet. Really my tests or specifications in this case should always fail first and then it’s up to me to do what ever is required to make them spec pass…. Even if involves secret underground Artic bases… Eerrmm OK, maybe not. Anyway, as you can tell I’ve added the first specification in at the top to intentionally fail. Let’s make this pumpkin pass. Make your auction.rb look like this:
class Auction < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :description
validates_numericality_of :starting_bid
end
If you run the specifications now you’ll see that they all now pass.
Step nine – I’m going to digress for a minute and talk about stubs and mocks. If you don’t already know what a stub or a mock is then here is a good description of the various terms. Now you’ve probably been told to use stubs and/or mocks when working with systems external to your application, 3rd party libraries or dependencies that aren’t solely related to what you’re currently testing. In this case the database is a dependency so lets stub out any database calls. The only problem is that we’re currently not hitting the database, so let write a specification that would normally hit the database, but errrm doesn’t. Sorry if I sound like a fortune cookie. Add this context and specifcation to the auction_spec.rb file.
context "An auction that we want to remove" do
setup do
@auction = Auction.new
@auction.attributes = AuctionSpecHelper.valid_auction_attributes
@auction.stub!(:save!).and_return(:true)
end
specify "should be able to deactivate auction" do
@auction.deactivate!
@auction.active?.should_equal false
end
end
The first thing you’ll see is that I’ve actually stubbed out the default Activerecord save! method of the auction model so that it doesn’t hit the database. You currently don’t see me calling save! but thats a coming implementation detail which will become obvious in a few minutes. Of course if you try running the above you’ll get a few errors, the first being that there isn’t a deactivate! method on auction yet. Let’s fix that now, inside auction.rb add:
def deactivate!
self.active = false
#Aha! The fabled save! method!!!
self.save!
end
OK, the spec should now pass, but you know what? Call me picky but I’d like to hide the active attribute of the model, I don’t want any Tom, Dick or Tony Blair playing with the auction innards. Let’s make the following modifications:
In auction.rb add:
def activated?
self.active?
end
And then change the previous spec to:
specify "should be able to deactivate auction" do
@auction.deactivate!
@auction.activated?.should_equal false
end
The specifications should now still pass.
Step ten – Let’s now interact with another model, in this case it’s going to be a user model as our auction belongs_to one owner who created the auction. Things are going to start getting interesting. Add the following context and specification to your auction_spec.rb file:
context "An auction with an owner" do
setup do
@auction = Auction.new
@auction.attributes = AuctionSpecHelper.valid_auction_attributes
@owner = mock('user')
@owner.stub!(:new_record?).and_return(false)
#make sure you put in the Activerecord type checking hack in
#the spec_helper.rb file or this bit will go BOOM BOOM
@auction.owner = @owner
end
specify "should have an associated owner" do
@auction.owner.should_not_equal nil
end
end
OK, so this isn’t a very helpful test/spec in itself. However did you notice that we didn’t drop to the command line, run the RSpec model generator, create a User model migration, decide what fields to put into our migration, run the migration and then add various methods to our User class that our Auction model might need to interact with. Instead we can concentrate purely on our Auction model’s business logic and it’s interfaces/interactions with other models. You’ll find that by using stubs and mocks it allows you to experiment a little more easily without detracting from your train of thought.
I think here’s a good place to stop for now. Next time in part two I’ll introduce you lovely people to more advanced examples of mocking, but first some sleep. Good night chaps (and chapettes).
Anti-theft and anti traffic warden for your car
February 19th, 2007
Overheard octopod on #Caboose, Eye of Sauron anti-theft device for you car;).
Tagged with Eye of sauron
Barcamp London 2
February 18th, 2007
Phew! Both Damien and I are soooo tired. Barcamp London ended just a few hours ago and as usual it was a fun and crazy weekend. There were many interesting talks, lots of great people and much fun to be had. I can’t wait till the next Barcamp!
Unfortunately I only had the camera on my Sony mobile phone to talk pictures with, which is why the quality of the photos isn’t terribly sharp, but all the same they’re up on our Flickerstream to be seen.
A big thank you to Ian Forrester, all the Barcamp organisors and the sponsors for making this possible!
Tagged with Barcamplondon2
Ruby on Rails Exchange
February 12th, 2007
Well, right at the last minute I managed to get a seat at the Ruby on Rails at Skills Matter. Overall I found it quite enjoyable and glad I managed to take a day out of my mad schedule to attend.
Talks of note for me were Chad Fowlers talk on Quick and clean Rails, Tom Locke’s Hobo demonstration and Ben Griffith’s talk on testing.
Of particular note was Chad Fowler describing how Ruby is designed/best used by smart programmers who know what they’re doing. He continued to explain that if put into the wrong hands Ruby gives a bad programmer enough rope to hang himself with. And this is something I have to totally agree with, as over the past two and a half years I’ve either audited or rewritten some very crazily written Ruby on Rails projects. These were coded by either people trying to write large commercial applications after reading the Agile Web development with Rails book, or written by people who didn’t have a good grounding in Ruby and/or web application architecture. There’s nothing wrong with this if it’s a simple site with a small number of users, but not when it’s a high usage site that people expect to be available around the clock.
After everyones talks were over Skills Matter were nice enough to take everyone down to Fluid for some drinks, with the first one hundred being on the house. Overall a very nice end to an interesting day.
Netbeans == Smarter Ruby editing
February 12th, 2007
You’ve all heard that Sun hired some of the JRuby guys and that they’ve been beavering away on improving Ruby running within the JVM. One of the by products of this has been the inclusion of Ruby code editing into Netbeans, an IDE usually associated with Java development and until a year ago was the butt of every other Java IDE’s jokes.
Now I’m a happy Textmate user and have been using it for quite a while now, but I have to admit there are various things that have become annoying such as slow search, no inbuilt refactoring support, intellisense and just “understanding” my code within the context of the project. Now I don’t need these things but it would sure make working with large Ruby on Rails projects a heck of a lot easier.

If you want to check out some of the smarter intellisense features for Ruby that are to be found in Netbeans then you’re going to currently have to do a little bit of work. There’s currently a wiki page up detailing everything you need to do in order to build the latest Ruby modules for the IDE. A link to precompiled binaries that can be added to an existing install of Netbeans can also be found on the page. A word of caution though that it’s all very work in progress and bad things may happen so I wouldn’t go dumping your copy of Textmate just yet.
Tagged with Netbeans, Ruby editing
Merger
February 6th, 2007
You may be wondering what I, Jonathan, am doing writing an entry in the Bamboo blog? We’ll if you haven’t guessed it already both New Bamboo and Agile Evolved decided late last year to form a new company. OK, that’s a lie, to tell the truth, I lost the company to Damien and Max over a World of Warcraft match.
But seriously, the reason that Agile Evolved joined forces with New Bamboo was to combine all of our talents to form the UK’s premier Ruby on Rails consultancy. With us all coming together you’ll have:
- Max and Damien’s impeccable experience with working with cutting edge start ups
- My experience of applying web 2.0 technologies/principles in the enterprise
- Dr Fishers knowledge of AI, search algorithms et al
- And finally Marek’s deep understanding of all things Ruby
The first thing we did when the merger occurred was to make a cup of Early Grey. The second thing we did was to finally kit the office out with some furniture. Previously I’d gone for the minimalist approach of a few desks and some Aerons, yep I never said I was the artistic one in the company. Pictures of our new refurbished office can be found in our Flickr account.
If you’re ever around the King’s Cross area feel more than free to pop in for a chat. However don’t expect to escape without a game of Wii tennis!
Tagged with New Bamboo, Agile Evolved, Company Merger





