Going through the rspec docs i found these lines of code in yielding section of this page http://rubydoc.info/gems/rspec-expectations/frames
Can anyone explain what each line of code in the yielding section does step-by-step
What does expect { |b| 5.tap(&b) }.to yield_control
do?
It is expecting that the code given in the block invokes yield
statement.
The code given in the block (viz. { |b| 5.tap(&b) }
) calls the ruby 1.9 tap method which has a yield
statement within it's implementation.
So the statement is effectively asserting that ruby 1.9's tap method has a yield
statement. :-)
To better understand this statement, try the following code example:
order.rb
file
class Order
end
order_spec.rb
file
require 'rspec-expectations'
require './order'
describe Order do
it "should yield regardless of yielded args" do
expect { |b| 5.tap(&b);puts "The value of b is #{b.inspect}" }.to yield_control
end
end
Output from executing the spec:
$ rspec yield_spec.rb
Order
The value of b is #<RSpec::Matchers::BuiltIn::YieldProbe:0x000001008745f0 @used=true, @num_yields=1, @yielded_args=[[5]]>
should yield regardless of yielded args
Finished in 0.01028 seconds
1 example, 0 failures
To understand the other lines in the yielding section, similarly include the expect
statements in the spec file as follows:
it "should yield with no args" do
expect { |b| Order.yield_if_true(true, &b) }.to yield_with_no_args
end
it "should yield with 5 args" do
expect { |b| 5.tap(&b) }.to yield_with_args(5)
end
it "should yield with integer args" do
expect { |b| 5.tap(&b) }.to yield_with_args(Fixnum)
end
it "should yield with string args" do
expect { |b| "a string".tap(&b) }.to yield_with_args(/str/)
end
it "should yield 1,2,3 successively" do
expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3)
end
it "should yield ([:a,1], [:b,2]) successively" do
expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2])
end
Note: The yield_if_true
method used in the second line seems to be removed from where it was originally defined; I got it go work by adding it into the Order class as follows:
class Order
def self.yield_if_true(flag)
yield if flag
end
end