Rspec -- Test If Method Called Its Block Parameter

RSpec -- test if method called its block parameter

I usually do something like

a = 1
b.go { a = 2}
a.should == 2

RSpec -- test if block called with block defined in before

Try something like this (untested by me):

context "the node definition using block of code" do
let(:node){
node = Node.new "arg1", "arg2", node_block
# more complex stuff here
node
}
context "checking the block is called" do
let(:node_block) {
double = double("node_block")
double.should_receive("some kind of arg").and_return("something")
# this will now cause a fail if it isn't called
double
}
it "should call the block" do
node.blah()
end
end

let(:node_block) {
# some real code
}

subject { node.blah() }
it { should == 2 }
# ...
end

So that's a very shaky piece of code (you'll have to fill in the gaps as you didn't give very much to go on, and let is obviously a lambda too, which could mean you've got to play around with it a bit) that uses let and a double to check it's called, and avoids using before, which is really for side effects not setting up variables for use in the specs.

@zetetic makes a very insightful comment that you're not testing behaviour here. I'm not against using rspec for doing more unit test style stuff (guidelines are made to be broken), but you might ask how later tests will pass when using a real block of code if that block isn't being called? In a way, I'm not even sure you need to check the block is called, but only you know.

RSpec. Testing arguments of block call

It's actually really straight forward.

it "responds to data" do
DropboxApi.read_path do |batch|
expect(batch).to respond_to(:data)
end
end

it "has a count of 6" do
DropboxApi.read_path do |batch|
expect(batch.data.count).to eq(6)
end
end

And if you really want it to look more terse, like your example you can do the following.

let(:batch) {
DropboxApi.read_path do |batch|
return batch
end
}

it { expect(batch).to respond_to(:data) }
it { expect(batch.data.count).to eq(6) }

Test if a method takes a block

How can I verify if Foobar#some_method takes a block.

Every method in ruby takes (can take) a block. It may simply choose not to yield. So that's what you need to check, I think: if the method yielded or not.

RSpec has a number of yield expectations: https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/yield-matchers

RSpec.describe "yield_control matcher" do
specify { expect { |b| MyClass.yield_once_with(1, &b) }.to yield_control }
specify { expect { |b| MyClass.dont_yield(&b) }.not_to yield_control }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.twice }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.exactly(2).times }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_least(1) }
specify { expect { |b| MyClass.yield_twice_with(1, &b) }.to yield_control.at_most(3).times }

end

So for your case it should be something like this:

expect{ foobar.some_method }.to yield_control

How to test a method with a parameter using RSpec?

my_param should be defined inside the it block or you should use let to define my_param

Inside it block

describe Job do
let(:job) { Job.new }

describe 'run_job' do
context 'success' do
it 'should pass' do
my_param = [{"job1" => "run"}, {"job2" => "run again"}]

test_result = job.run_job(my_param)
expect(test_result[0]["job1"]).to eq("run")
end
end
end
end

Using let

describe Job do
let(:job) { Job.new }

describe 'run_job' do
context 'success' do
let(:my_param) { [{"job1" => "run"}, {"job2" => "run again"}] }

it 'should pass' do
test_result = job.run_job(my_param)
expect(test_result[0]["job1"]).to eq("run")
end
end
end
end

Using before block

describe Job do
let(:job) { Job.new }

describe 'run_job' do
context 'success' do
before(:all) do
@my_param = [{"job1" => "run"}, {"job2" => "run again"}]
end

it 'should pass' do
test_result = job.run_job(@my_param)
expect(test_result[0]["job1"]).to eq("run")
end
end
end
end


Related Topics



Leave a reply



Submit