forked from rspec/rspec-mocks
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add cukes for new stub_const feature.
Closes rspec#144.
- Loading branch information
1 parent
ecfb7f6
commit e31f4a4
Showing
4 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
## Stubbing Constants | ||
|
||
Support is provided for stubbing constants. Like with method stubs, the | ||
stubbed constants will be restored to their original state when a method | ||
completes. | ||
|
||
``` ruby | ||
stub_const("Foo", fake_foo) | ||
Foo # => fake_foo | ||
``` | ||
|
||
Stubbed constant names must be fully qualified; the current module | ||
nesting is not considered. | ||
|
||
``` ruby | ||
module MyGem | ||
class SomeClass; end | ||
end | ||
|
||
module MyGem | ||
describe "Something" do | ||
let(:fake_class) { Class.new } | ||
|
||
it "accidentally stubs the wrong constant" do | ||
# this stubs ::SomeClass (in the top-level namespace), | ||
# not MyGem::SomeClass like you probably mean. | ||
stub_const("SomeClass", fake_class) | ||
end | ||
|
||
it "stubs the right constant" do | ||
stub_const("MyGem::SomeClass", fake_class) | ||
end | ||
end | ||
end | ||
``` | ||
|
||
When you stub a constant that is a module or a class, nested | ||
constants on the original module or class are not transferred | ||
by default, but you can use the `:transfer_nested_constants` | ||
option to tell rspec-mocks to transfer them: | ||
|
||
``` ruby | ||
class CardDeck | ||
SUITS = [:Spades, :Diamonds, :Clubs, :Hearts] | ||
NUM_CARDS = 52 | ||
end | ||
|
||
fake_class = Class.new | ||
stub_const("CardDeck", fake_class) | ||
CardDeck # => fake_class | ||
CardDeck::SUITS # => raises uninitialized constant error | ||
CardDeck::NUM_CARDS # => raises uninitialized constant error | ||
|
||
stub_const("CardDeck", fake_class, :transfer_nested_constants => true) | ||
CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts] | ||
CardDeck::NUM_CARDS # => 52 | ||
|
||
stub_const("CardDeck", fake_class, :transfer_nested_constants => [:SUITS]) | ||
CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts] | ||
CardDeck::NUM_CARDS # => raises uninitialized constant error | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
Feature: Stub Defined Constant | ||
|
||
Use `stub_const` to stub constants. When the constant is already defined, | ||
the stubbed value will replace the original value for the duration of the | ||
example. | ||
|
||
Scenario: Stub top-level constant | ||
Given a file named "stub_const_spec.rb" with: | ||
"""ruby | ||
FOO = 7 | ||
describe "stubbing FOO" do | ||
it "can stub FOO with a different value" do | ||
stub_const("FOO", 5) | ||
FOO.should eq(5) | ||
end | ||
it "restores the stubbed constant when the example completes" do | ||
FOO.should eq(7) | ||
end | ||
end | ||
""" | ||
When I run `rspec stub_const_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Stub nested constant | ||
Given a file named "stub_const_spec.rb" with: | ||
"""ruby | ||
module MyGem | ||
class SomeClass | ||
FOO = 7 | ||
end | ||
end | ||
module MyGem | ||
describe SomeClass do | ||
it "stubs the nested constant when it is fully qualified" do | ||
stub_const("MyGem::SomeClass::FOO", 5) | ||
SomeClass::FOO.should eq(5) | ||
end | ||
end | ||
end | ||
""" | ||
When I run `rspec stub_const_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Transfer nested constants | ||
Given a file named "stub_const_spec.rb" with: | ||
"""ruby | ||
module MyGem | ||
class SomeClass | ||
FOO = 7 | ||
end | ||
end | ||
module MyGem | ||
describe SomeClass do | ||
let(:fake_class) { Class.new } | ||
it "does not transfer nested constants by default" do | ||
stub_const("MyGem::SomeClass", fake_class) | ||
expect { SomeClass::FOO }.to raise_error(NameError) | ||
end | ||
it "transfers nested constants when using :transfer_nested_constants => true" do | ||
stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => true) | ||
SomeClass::FOO.should eq(7) | ||
end | ||
it "can specify a list of nested constants to transfer" do | ||
stub_const("MyGem::SomeClass", fake_class, :transfer_nested_constants => [:FOO]) | ||
SomeClass::FOO.should eq(7) | ||
end | ||
end | ||
end | ||
""" | ||
When I run `rspec stub_const_spec.rb` | ||
Then the examples should all pass | ||
|
50 changes: 50 additions & 0 deletions
50
features/stubbing_constants/stub_undefined_constant.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
Feature: Stub Undefined Constant | ||
|
||
Use `stub_const` to stub constants. When the constant is not already defined, | ||
all the necessary intermediary modules will be dynamically created. When the | ||
example completes, the intermediary module constants will be removed to return | ||
the constant state to how it started. | ||
|
||
Scenario: Stub top-level constant | ||
Given a file named "stub_const_spec.rb" with: | ||
"""ruby | ||
describe "stubbing FOO" do | ||
it "can stub undefined constant FOO" do | ||
stub_const("FOO", 5) | ||
FOO.should eq(5) | ||
end | ||
it "undefines the constant when the example completes" do | ||
expect { FOO }.to raise_error(NameError) | ||
end | ||
end | ||
""" | ||
When I run `rspec stub_const_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Stub nested constant | ||
Given a file named "stub_const_spec.rb" with: | ||
"""ruby | ||
module MyGem | ||
class SomeClass | ||
end | ||
end | ||
module MyGem | ||
describe SomeClass do | ||
it "can stub an arbitrarily deep constant that is undefined" do | ||
defined?(SomeClass::A).should be_false | ||
stub_const("MyGem::SomeClass::A::B::C", 3) | ||
SomeClass::A::B::C.should eq(3) | ||
SomeClass::A.should be_a(Module) | ||
end | ||
it 'undefines the intermediary constants that were dynamically created' do | ||
defined?(SomeClass).should be_true | ||
defined?(SomeClass::A).should be_false | ||
end | ||
end | ||
end | ||
""" | ||
When I run `rspec stub_const_spec.rb` | ||
Then the examples should all pass |