Skip to content

Commit

Permalink
Merge pull request #183 from alindeman/hide_const
Browse files Browse the repository at this point in the history
Add support to temporarily remove constants
  • Loading branch information
alindeman committed Oct 21, 2012
2 parents eb931c1 + 0a9316f commit fd53183
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 56 deletions.
3 changes: 2 additions & 1 deletion features/.nav
Expand Up @@ -18,9 +18,10 @@
- explicit.feature
- general_matchers.feature
- type_matchers.feature
- stubbing_constants:
- mutating_constants:
- stub_defined_constant.feature
- stub_undefined_constant.feature
- hiding_defined_constant.feature
- outside_rspec:
- configuration.feature
- standalone.feature
@@ -1,4 +1,6 @@
## Stubbing Constants
## Mutating Constants

### Stubbing

Support is provided for stubbing constants. Like with method stubs, the
stubbed constants will be restored to their original state when an
Expand Down Expand Up @@ -60,3 +62,21 @@ CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts]
CardDeck::NUM_CARDS # => raises uninitialized constant error
```

### Hiding

Support is also provided for hiding constants. Hiding a constant temporarily
removes it; it is restored to its original value after the test completes.

```ruby
FOO = 42
hide_const("FOO")
FOO => NameError: uninitialized constant FOO
```

Like stubbed constants, names must be fully qualified.

Hiding constants that are already undefined has no effect.

```ruby
hide_const("NO_OP")
```
64 changes: 64 additions & 0 deletions features/mutating_constants/hiding_defined_constant.feature
@@ -0,0 +1,64 @@
Feature: Hide Defined Constant

Use `hide_const` to remove a constant for the duration of a test.

Scenario: Hide top-level constant
Given a file named "hide_const_spec.rb" with:
"""ruby
FOO = 7
describe "hiding FOO" do
it "can hide FOO" do
hide_const("FOO")
expect { FOO }.to raise_error(NameError)
end
it "restores the hidden constant when the example completes" do
FOO.should eq(7)
end
end
"""
When I run `rspec hide_const_spec.rb`
Then the examples should all pass

Scenario: Hide nested constant
Given a file named "hide_const_spec.rb" with:
"""ruby
module MyGem
class SomeClass
FOO = 7
end
end
module MyGem
describe SomeClass do
it "hides the nested constant when it is fully qualified" do
hide_const("MyGem::SomeClass::FOO")
expect { SomeClass::FOO }.to raise_error(NameError)
end
it "restores the hidden constant when the example completes" do
MyGem::SomeClass::FOO.should eq(7)
end
end
end
"""
When I run `rspec hide_const_spec.rb`
Then the examples should all pass

Scenario: Hiding undefined constant
Given a file named "hide_const_spec.rb" with:
"""
describe "hiding UNDEFINED_CONSTANT" do
it "has no effect" do
hide_const("UNDEFINED_CONSTANT")
expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
end
it "is still undefined after the example completes" do
expect { UNDEFINED_CONSTANT }.to raise_error(NameError)
end
end
"""
When I run `rspec hide_const_spec.rb`
Then the examples should all pass
20 changes: 18 additions & 2 deletions lib/rspec/mocks/example_methods.rb
Expand Up @@ -79,11 +79,27 @@ def allow_message_expectations_on_nil
# CardDeck::SUITS # => our suits array
# CardDeck::NUM_CARDS # => uninitialized constant error
def stub_const(constant_name, value, options = {})
ConstantStubber.stub(constant_name, value, options)
ConstantMutator.stub(constant_name, value, options)
end

# Hides the named constant with the given value. The constant will be
# undefined for the duration of the test.
#
# Like method stubs, the constant will be restored to its original value
# when the example completes.
#
# @param constant_name [String] The fully qualified name of the constant.
# The current constant scoping at the point of call is not considered.
#
# @example
#
# hide_const("MyClass") # => MyClass is now an undefined constant
def hide_const(constant_name)
ConstantMutator.hide(constant_name)
end

private

def declare_double(declared_as, *args)
args << {} unless Hash === args.last
args.last[:__declared_as] = declared_as
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/mocks/framework.rb
Expand Up @@ -19,4 +19,4 @@
require 'rspec/mocks/space'
require 'rspec/mocks/serialization'
require 'rspec/mocks/any_instance'
require 'rspec/mocks/stub_const'
require 'rspec/mocks/mutate_const'

0 comments on commit fd53183

Please sign in to comment.