Wrapping a Context in a Context (in RSpec)

A few days ago I blogged about solving a sticky problem by overwriting the “new” method on an ActiveRecord object inside a test (spec). Something I should have mentioned is that this is dangerous because if another spec (test) tries to call new and gets executed after the dangerous spec/test is run, then of course it won’t have the original new method. And it’s a very hard error to track down unless you know it’s been redefined. The solution to this, should you need to do it (and you probably won’t – any good mocking framework will probably do what you want), is to wrap a context around all the contexts that need it and use context_setup like this:

context 'When the situation demands it' do
context_setup do
Class SomeObject
def some_method_to_overwrite
#do whatever I want -- Bwaa ha ha!
end
end
end

context 'Some context' do
#specs go here
end

context 'Some other context' do
#more specs go here
end
end

After it drops out of the context, the method isn’t redefined anymore. Yeah! Of course, to be real good and safe you should probably alias the new method in the setup and reassign it back in the teardown. But this works too.

Comments

David Chelimsky said…
Which entry talks about overriding #new on an AR subclass? I can't find it.

Regardless, for the record, nesting contexts is not officially supported in any way.

If you want to have #new behave differently in a spec, I'd recommend using the mock framework as demonstrated at http://pastie.caboo.se/46766.

The fact that the second spec is working correctly shows that #new is restored to its original condition after the first spec.

Popular posts from this blog

Point Inside a Polygon in Ruby

What's a Good Flog Score?

SICP Wasn’t Written for You