Skip to content

Instantly share code, notes, and snippets.

@hynkle
Last active December 14, 2015 02:29
Show Gist options
  • Save hynkle/5014239 to your computer and use it in GitHub Desktop.
Save hynkle/5014239 to your computer and use it in GitHub Desktop.

In my codebase, I've got something like the following, where Foo, Bar, and Baz are classes:

case o
when Foo then process!
when Bar then trash!
when Baz then flag!
else raise ArgumentError, "unexpected type #{o.class}"
end

A case statement uses the === operator (really just a method) to compare each when's subject with case's object, so in this case by checking Foo === o and then (if not truthy) Bar === o. The semantics of a class's === method is to tell you whether the argument (i.e. o) is an instance of the class (or one of its subclasses).

This behavior's lovely and convenient. Fine.

But now suppose you have a spec that exercises this code, and in your spec, you don't want to have to build out a real Foo or a real Bar, as they happen to be complicated to use and you really only need one or two pieces of their behavior. It's normal enough to use mocks in your specs, after all, and since this isn't Foo's spec or Bar's spec, you really don't want to rely on them. So you want an object o such that for some particular class klass, klass === o. Welp, tough! This happens down at the C level (assuming you're using MRI, at least—but at any rate, happening at the VM level). It seems like even if you wrote a C extension, the internals work in such a way that by making this test pass, your mock object would actually get all the behavior that a real instance of klass has. Well then.

Two options, both sucky:

  1. Rewrite your code just because your current implementation is unspeccable, or
  2. Build out an actual instance of klass in your spec.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment