Skip to content

Commit

Permalink
Merge pull request #326 from rspec/feature_for_allow
Browse files Browse the repository at this point in the history
Documentation for allow (counterpart to stub in the expect syntax)
  • Loading branch information
JonRowe committed Jun 28, 2013
2 parents e2a69a9 + 3c1780a commit 0c855d8
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 33 deletions.
26 changes: 26 additions & 0 deletions features/message_expectations/allow_any_instance_of.feature
@@ -0,0 +1,26 @@
Feature: allow a message on any instance of a class

Use `allow_any_instance_of(Class).to receive` when you want to configure how
instances of the given class respond to a message without setting an
expectation that the message will be received.

Scenario: allowing a message on any instance of a class
Given a file named "example_spec.rb" with:
"""ruby
describe "any_instance.should_receive" do
before do
allow_any_instance_of(Object).to receive(:foo).and_return(:return_value)
end
it "allows any instance of the class to receive the message" do
o = Object.new
expect(o.foo).to eq(:return_value)
end
it "passes even if no instances receive that message" do
o = Object.new
end
end
"""
When I run `rspec example_spec.rb`
Then the examples should all pass
31 changes: 3 additions & 28 deletions features/message_expectations/expect_any_instance_of.feature
@@ -1,13 +1,9 @@
Feature: expect/allow a message on any instance of a class
Feature: expect a message on any instance of a class

Use `expect_any_instance_of(Class).to receive` to set an expectation that one
(and only one) instance of a class receives a message before the example is
completed. The spec will fail if no instance receives a message.

Use `allow_any_instance_of(Class).to receive` when an instance of a class may
respond to a particular message. This will not set an expectation on any instance
so the spec will not fail if no instance receives the message.

Scenario: expect a message on any instance of a class
Given a file named "example_spec.rb" with:
"""ruby
Expand All @@ -21,32 +17,11 @@ Feature: expect/allow a message on any instance of a class
expect(o.foo).to eq(:return_value)
end
it "fails if no instance receives that message" do
it "fails unless an instance receives that message" do
o = Object.new
end
end
"""
When I run `rspec example_spec.rb`
Then the output should contain "2 examples, 1 failure"
And the output should contain "1) expect_any_instance_of fails if no instance receives that message"

Scenario: allowing a message on any instance of a class
Given a file named "example_spec.rb" with:
"""ruby
describe "any_instance.should_receive" do
before do
allow_any_instance_of(Object).to receive(:foo).and_return(:return_value)
end
it "allows any instance of the class to receive the message" do
o = Object.new
expect(o.foo).to eq(:return_value)
end
it "wont fail if no instances receive that message" do
o = Object.new
end
end
"""
When I run `rspec example_spec.rb`
Then the examples should all pass
And the output should contain "1) expect_any_instance_of fails unless an instance receives that message"
30 changes: 28 additions & 2 deletions features/method_stubs/README.md
Expand Up @@ -3,7 +3,11 @@
# create a double
obj = double()

# specify a return value
# specify a return value using `:expect` syntax
allow(obj).to receive(:message) { :value }
allow(obj).to receive(:message).and_return(:value)

# specify a return value using `:should` syntax
obj.stub(:message) { :value }
obj.stub(:message => :value)
obj.stub(:message).and_return(:value)
Expand All @@ -14,30 +18,50 @@ block contents are evaluated lazily when the `obj` receives the

### Fake implementation

allow(obj).to receive(:message) do |arg1, arg2|
# set expectations about the args in this block
# and/or return value
end

obj.stub(:message) do |arg1, arg2|
# set expectations about the args in this block
# and/or set a return value
# and/or return a value
end

### Raising/Throwing

allow(obj).to receive(:message).and_raise("this error")
allow(obj).to receive(:message).and_throw(:this_symbol)

obj.stub(:message).and_raise("this error")
obj.stub(:message).and_throw(:this_symbol)

You can also use the block format:

allow(obj).to receive(:message) { raise "this error" }
allow(obj).to receive(:message) { throw :this_symbol }

obj.stub(:message) { raise "this error" }
obj.stub(:message) { throw :this_symbol }

### Argument constraints

#### Explicit arguments

allow(obj).to receive(:message).with('an argument') { ... }

obj.stub(:message).with('an argument') { ... }
obj.stub(:message).with('more_than', 'one_argument') { ... }

#### Argument matchers

allow(obj).to receive(:message).with(anything()) { ... }
allow(obj).to receive(:message).with(an_instance_of(Money)) { ... }
allow(obj).to receive(:message).with(hash_including(:a => 'b')) { ... }
allow(obj).to receive(:message).with(array_including(1,2,3)) { ... }
# or
allow(obj).to receive(:message).with(array_including([1,2,3])) { ... }

obj.stub(:message).with(anything()) { ... }
obj.stub(:message).with(an_instance_of(Money)) { ... }
obj.stub(:message).with(hash_including(:a => 'b')) { ... }
Expand All @@ -47,4 +71,6 @@ You can also use the block format:

#### Regular expressions

allow(obj).to receive(:message).with(/abc/) { ... }

obj.stub(:message).with(/abc/) { ... }
6 changes: 5 additions & 1 deletion features/method_stubs/any_instance.feature
Expand Up @@ -6,6 +6,10 @@ Feature: stub on any instance of a class

Messages can be stubbed on any class, including those in Ruby's core library.

Note: You can use `allow_any_instance_of` when you don't have a reference
to the object that receives a message in your test. For more information,
see the message_expectations/allow_any_instance_of feature.

Scenario: any_instance stub with a single return value
Given a file named "example_spec.rb" with:
"""ruby
Expand Down Expand Up @@ -129,4 +133,4 @@ Feature: stub on any instance of a class
end
"""
When I run `rspec stub_chain_spec.rb`
Then the examples should all pass
Then the examples should all pass
7 changes: 6 additions & 1 deletion features/method_stubs/as_null_object.feature
Expand Up @@ -16,7 +16,12 @@ Feature: as_null_object
null_object.should respond_to(:an_undefined_method)
end
it "allows explicit stubs" do
it "allows explicit stubs using expect syntax" do
allow(null_object).to receive(:foo) { "bar" }
expect(null_object.foo).to eq("bar")
end
it "allows explicit stubs using should syntax" do
null_object.stub(:foo) { "bar" }
null_object.foo.should eq("bar")
end
Expand Down
44 changes: 44 additions & 0 deletions features/method_stubs/simple_return_value_with_allow.feature
@@ -0,0 +1,44 @@
Feature: allow with a simple return value

Use the `allow` method with the `receive` matcher on a test double or a real
object to tell the object to return a value (or values) in response to a given
message. Nothing happens if the message is never received.

Scenario: stub with no return value
Given a file named "example_spec.rb" with:
"""ruby
describe "a stub with no return value specified" do
let(:collaborator) { double("collaborator") }
it "returns nil" do
allow(collaborator).to receive(:message)
expect(collaborator.message).to be(nil)
end
end
"""
When I run `rspec example_spec.rb`
Then the examples should all pass

Scenario: stubs with return values
Given a file named "example_spec.rb" with:
"""ruby
describe "a stub with a return value" do
context "specified in a block" do
it "returns the specified value" do
collaborator = double("collaborator")
allow(collaborator).to receive(:message) { :value }
expect(collaborator.message).to eq(:value)
end
end
context "specified with #and_return" do
it "returns the specified value" do
collaborator = double("collaborator")
allow(collaborator).to receive(:message).and_return(:value)
expect(collaborator.message).to eq(:value)
end
end
end
"""
When I run `rspec example_spec.rb`
Then the examples should all pass
24 changes: 23 additions & 1 deletion features/method_stubs/stub_implementation.feature
Expand Up @@ -3,7 +3,29 @@ Feature: stub with substitute implementation
You can stub an implementation of a method (a.k.a. fake) by passing a block
to the `stub` method.

Scenario: stub implementation
Scenario: stub implementation using `expect` syntax
Given a file named "stub_implementation_spec.rb" with:
"""ruby
describe "a stubbed implementation" do
it "works" do
object = Object.new
allow(object).to receive(:foo) do |arg|
if arg == :this
"got this"
elsif arg == :that
"got that"
end
end
expect(object.foo(:this)).to eq("got this")
expect(object.foo(:that)).to eq("got that")
end
end
"""
When I run `rspec stub_implementation_spec.rb`
Then the output should contain "1 example, 0 failures"

Scenario: stub implementation using `should` syntax
Given a file named "stub_implementation_spec.rb" with:
"""ruby
describe "a stubbed implementation" do
Expand Down

0 comments on commit 0c855d8

Please sign in to comment.