Closed myronmarston closed 12 years ago
This all sounds good to me except:
There's a caveat to that last point: if, during the example, the value of the constant is changed by the user (e.g. because the example loads a file that redefines the constant, or whatever), then the constant is not restored to its original value; the thinking is that if the user is changing the constant on their own then they know what they're doing and we shouldn't change it out underneath them.
Personally, I'd rather be able to rely on trusting that no matter what happens in my examples, the state is restored at the end of each.
I don't feel very strongly either way on that point. At the time I was working on the code in rspec fire, it made sense to me to do it that way, but in retrospect, I'm not sure it was the right choice.
Also, I just tried this:
class Foo
def self.bar
"original bar"
end
end
describe Foo do
specify do
Foo.stub(:bar) { "stubbed bar" }
def Foo.bar; "overridden bar"; end
end
specify do
Foo.bar.should eq("original bar")
end
end
...and I'm seeing that stubbed methods get restored even if they get re-defined by the user after being stubbed. I think rspec-mocks should be consistent here, and always restore the original state of constants no matter what.
I'd rather have the cleanup happen unconditionally as well.
:+1:
This is just great. Would allow me to get rid of my home grown stub_const
that does not "rollback"!
This would be awesome because it means less code for me to maintain in rspec-fire
:P
(which actually isn't a problem because @myronmarston does such a good job of it...)
A few months ago, I added constant stubbing functionality to @xaviershay's rspec-fire. From the start, I thought this would be a great addition to rspec-mocks, but wanted to vet it and work out the kinks in rspec-fire first. At this point, i'd like to get feedback on adding it rspec-mocks. I know that @garybernhardt is eager to see it added here.
Here's how the feature works in rspec-fire (and how I'd imagine it working in rspec-mocks):
stub_const("Foo", some_object)
. For the duration of the example, the constantFoo
will be a reference tosome_object
.stub_const("A::B::C::D", 5)
will makeA::B::C::D
equal to 5 even if none of those modules previously existed.stub_const
also supports a:transfer_nested_constants
option. This is sometimes needed when stubbing a module constant that is a namespace for other constants--without this option, a user would cut off their access toA::B
when they stubA
. With this option, you can passtrue
to have it transfer all nested constants, or pass a list of constants to transfer. Here's an example:I've found this to be very useful for a couple reasons:
So...I'd love to get both feedback from the community and buy-in from other rspec contributors before I start working on this.
Thoughts?
/cc @dchelimsky @justinko @garybernhardt @xaviershay @freelancing-god @coreyhaines