Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Railsconf: Don't mock yourself out – Dave Chelimsky

Pivotal Labs
Tuesday, May 5, 2009

Martin Fowler says Mocks Aren’t Stubs and talks about Classical and Mockist Teting. Dave shows slightly amusing set of photos about “ists” – Rubyists etc. Ist bin ein red herring. The big issue here is when to use a mock.

Overview of Stubs and Mocks

Terminology: test double – an object standing in for a real object (like a stunt double).

customer = Object.new
logger = Object.new
customer.stub(:name).and_return('Joe Customer')
logger.should_receive(:log)

customer.should_receive(:name).and_return('Joe customer')
# bad - very tightly bound to implementation

customer.stub(:name).and_return('Joe customer')
# also tighly bound to implementation
  • Stubs are often used like mocks, mocks used like stubs.
  • We verify stubs by checking state after an interaction.
  • We tell mocks to verify interactions.
  • Sometimes stubs just make the system run.

When are method stubs helpful?

Isolation from non-determinism: Simulate random value geneators or Time.now.

Isolation from external depedencies: e.g. external database or network. Have gave anexample or an ActiveMerchant test that takes 1.5s to run, and stubbed out gateway.stubs(:authorize).returns(AM:Billing:Response.new(true, ‘ignore’)

Polymorphic collaborators: e.g. employee that knows how to pay itself, uses a strategy. paymet_strategy = mock() employee = E.new(p_s)
p_s.expects(:pay)
employee.pay

mixins/plugins

When are messsage expectations helpful?

side effects: background processing

caching: only call a network zipcode lookup once

validator = mock()
zipcode = Zipcode.new("01234", validator)
validator.should_receive(:valid?).with("01234").once
zipcode.valid?
zipcode.valid?

interface discovery: tool to discover the parts of the system that you haven’t really worked out yet. Mock something out that doesn’t exist yet, while designing its interface.

Isolation Testing

All of these concepts are Isolation Testing – testing an object in isolation from others. This is a good fit when you have lots of little objects (ravioli code, as opposed to spaghetti code).

Isolation Testing in Rails

Rails is calzone code. Three layers: View Controller Model. These 3 layers are not the whole picture: browser, router, database. Standard rails testing:

  • Unit tests: Testing in isolation. Test model classes (repositories), model objects, database.
  • Functional tests: 2 or more non-trivial components work together. Test model classes, model objcets, database, views, controllers.
  • Integration tests: Test model classes, model objects, database views controllers, routing/sessions.
    This is !DRY

Mocking and stubbing you can do in Rails

Partials in view specs:

before :each do
  template.stub(:render).with(:partial => anything)
end

...

template.should_receive(:render).with(:partial => 'nav')

Conditional branches in controllers: Stub new and save! methods of models.

Dave has a new project stubble on github: You will need to build RSpec locally to use this for now.

stubbing(Registration) do
#  Stubs ActiveRecord finder and save methods on model

Chains are a new RSpec feature: user.stub_chain – some people say this is a test no-no, use with caution.

Guidelines, concerns & Common Pitfalls

  • Keep things simple
  • Try to avoid tight coupling
  • Complex setup is a red flag for design issues
  • Don’t stub and mock the object that you are testing
  • Concern: impedes refactoring (but some say refactoring is improving design without changing behavior, so tests should not change. This really depends what level you are refactoring at).
  • Concern: false positives
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Add New Comment Cancel reply

Your email address will not be published.

Pivotal Labs

Pivotal Labs

Recent Posts

  • Does the set of all sets contain itself?
  • Standup 3/8/2012
  • Standup 3/7/2012
Subscribe to Pivotal's Feed

Author Topics

riddles (1)
agile (167)
capistrano (2)
rails (26)
movember (1)
git (10)
railsdoc (1)
object-design (1)
bdd (3)
cucumber (3)
linkedin (1)
oauth (1)
ruby (17)
tdd (2)
lvh.me (1)
rails 3.1.1 (1)
selenium (6)
homebrew (1)
mysql (5)
rvm (1)
sproutcore (1)
paperclip (2)
pry (1)
amazon (1)
heroku (1)
rails3 (2)
jasmine (3)
design (3)
process (12)
productivity (8)
learning (1)
olin (1)
migrations (2)
mongodb (2)
devise (2)
javascript (13)
rubymine (4)
ipad (1)
whurl (1)
head.js (1)
pairing (2)
tools (4)
pair programming (1)
rspec (10)
rspec2 (1)
ruby19 (1)
incubation (3)
startup (5)
api (1)
presenter (1)
vanna (1)
pivotal tracker (5)
capybara (1)
fakeweb (1)
webmock (1)
intern (1)
ruby on rails (25)
meetup (1)
textmate (1)
testing (20)
solr (4)
nyc-standup (11)
community (1)
opensource (3)
activerecord (4)
chrome (1)
mp4 (1)
activeresource (1)
flash (3)
neo4j (1)
nginx (1)
rsoc (1)
meta programming (1)
agile standup (7)
government (3)
webos (4)
xss (1)
jquery (1)
bundler (2)
ci (3)
gems (5)
postgresql (1)
geminstaller (1)
gemcutter (1)
cloud (2)
rack (2)
refraction (1)
gem (5)
refactoring (1)
validations (1)
webrat (1)
engine-yard (1)
firefox (2)
jsunit (1)
mongrel (2)
thin (1)
unicorn (1)
facebook (1)
rubygems (5)
jruby (1)
actioncontroller (1)
rails 2.3 (1)
palmpre (1)
autotest (1)
mac (2)
hosting (1)
goruco (11)
database (3)
railsconf (11)
gogaruco (4)
deployment (4)
github (1)
ie (1)
ajax (1)
intellij (1)
json (1)
asset packaging (1)
polonium (1)
character encoding (1)
utf-8 (1)
test (3)
civics (1)
hpricot (1)
rake (3)
sms (1)
unicode (1)
iphone (1)
java (1)
safari (1)
memory leaks (1)
rr (3)
editor (1)
css (1)
nyc (3)
performance (5)
fun (5)
enterprise rails (1)
health (1)
new and cool (1)
general (2)
treetop (1)
errors (1)
stack (1)
trace (1)
cache (1)
cookies (1)
freesoftware (1)
conferences (1)
development (1)
driven (1)
proxy (1)
caching (1)
peertopatent (1)
languages (1)
rest (2)
rubyforge (1)
sake (1)
file (1)
upload (1)
constants (1)
osx (1)
terminal (1)
pairprogramming (2)
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >