Using Hash to mock classes that respond to :[]

Hi

I’ve been doing this a while now. If I have a class that responds to :
[], and all I’m interested in stubbing is that method, then instead of
using a mock I just create a hash. (Similarly, you could create an
array when you are testing an Enumerable object.)

Example from code I just worked on, where uses MigrationGraph#[] looks
up graph vertices by name:

@migration_graph = {
# “name” => vertex
“changeset 1 migration 1” => @migration_a,
“changeset 1 migration 2” => @migration_b,
“changeset 2 migration 1” => @migration_c,
“changeset 2 migration 2” => @migration_d
}

What I’m really interested in is what happens to (some of) the four
migrations, not the migration graph itself.

I just wondered if anyone else did this. Generally doing unusual
things is a sign something is amiss.

Ashley


http://www.patchspace.co.uk/

I do that sort of thing pretty often.

I would just point out that you should avoid calling that mocking, since
there are no expectations in place and therefore no verification of the
specific way the code being specified interacts with the MigrationGraph.
According to the definitions in
Mocks Aren't Stubs (which are
apparently
from http://xunitpatterns.com/ but I haven’t read it), your hash is a
‘fake’
MigrationGraph.

-hume.

On Sun, May 18, 2008 at 5:13 AM, Ashley M.
[email protected]

On 19 May 2008, at 17:57, John D. Hume wrote:

I do that sort of thing pretty often.

I would just point out that you should avoid calling that mocking,
since there are no expectations in place and therefore no
verification of the specific way the code being specified interacts
with the MigrationGraph. According to the definitions in Mocks Aren't Stubs(which
are apparently from http://xunitpatterns.com/ but I haven’t read
it), your hash is a ‘fake’ MigrationGraph.

I hope you will forgive my sloppy use of TDD terms :slight_smile:

Actually I’ve never liked the use of the word “mock” to mean “verified
stub” or something similar, as “mock” and “fake” are synonyms in
everyday English. Maybe that’s because in RSpec you can create
expectations on any object (blank mocks or arbitrary other objects).

After all consider these two snippets (which is condensed from how you
would write real code):

@store = mock(“store”)
@store.stub!(:[]).and_return(1, 2) # implies you know the order of
calls
@store.should_receive(:[]).with(“a”).and_return(1)
@store.should_receive(:[]).with(“b”).and_return(2)

@store = { “a” => 1, “b” => 2 }
@store.should_receive(:[]).with(“a”).and_return(1)
@store.should_receive(:[]).with(“b”).and_return(2)

Only one is a mock by definition, but most sane code (and specs) would
behave the same with either. Surely since they both quack, they are
both ducks? As for the terms in the Fowler article, this is how I feel:

  • Dummy - I’m ok with this, I use symbols as dummies all the time
  • Fake - an “in-memory database” isn’t fake, it’s just an
    implementation that satisfies the needs of the code at hand (ie the
    spec). You could say a single-server database is fake, if a load-
    balanced cluster is needed to satisfy availability requirements.
  • Stubs - I think of a stub as a message-level concept, not an object-
    level one. To me, an object with stubs could be called a “fake” since
    it could never be used for a real purpose, no matter how simple the
    real task.
  • Mocks - in RSpec these are just objects that complain if sent an
    unexpected message. They become fake (my sense of the word) objects
    when you stub responses on them, although I prefer to call them mocks.

Alternative words that might make more sense in a duck-typed language
are “substitute” instead of “fake” (that’s what the use of a Hash
about would be) and “mock” instead of “stub”. I don’t know what you’d
call a Fowler mock in that case - maybe the idea doesn’t make sense
when any object can have expectations. I also don’t know what you’d
call a partial mock - an aberration, perhaps? :slight_smile:

I’m sure this is all nit-picking, but it’s taken me two years to learn
the “official” words and they still feel unnatural (which is why I
always fall back to my own version).

End rant!

Ashley

PS I think my use of a substitute Hash above is actually a symptom of
violation Tell Don’t Ask, I should probably pass the names of the
migrations to the MigrationGraph and have it unapply them all. That
would also clean up some other really hideous code in the Apply class
where #run goes poking around deleting stuff inside the graph (it’s a
did-I-really-write that moment). I wish I had the foresight to do
things right in the first place!


http://www.patchspace.co.uk/