RSpec allow/expect vs just expect/and_return
See the classic article Mocks Aren't Stubs. allow
makes a stub while expect
makes a mock. That is allow
allows an object to return X instead of whatever it would return unstubbed, and expect
is an allow
plus an expectation of some state or event. When you write
allow(Foo).to receive(:bar).with(baz).and_return(foobar_result)
... you're telling the spec environment to modify Foo
to return foobar_result
when it receives :bar
with baz
. But when you write
expect(Foo).to receive(:bar).with(baz).and_return(foobar_result)
... you're doing the same, plus telling the spec to fail unless Foo
receives :bar
with baz
.
To see the difference, try both in examples where Foo
does not receive :bar
with baz
.
Rspec double expect/allow anything
allow
and expect
methods can be used to stub methods/set expectations on particular method. Augmenting object with null object pattern is quite different, and thus uses different method call.
Please note that you should usually not use null object in area that is tested by particular test -- it is meant to imitate some part of the system that is side effect of tested code, which cannot be stubbed easily.
Rspec allow and expect the same method with different arguments
Seems like you are missing the .with('step2', anything)
it 'should call' do
allow(Temp::Service).to receive(:run).with('step1', anything).and_return(true)
# Append `.with('step2', anything)` here
expect(Temp::Service).to receive(:run).with('step2', anything) do |name, p|
expect(name).to eq 'step2' # you might not need this anymore as it is always gonna be 'step2'
expect(p['arg3']).not_to be_nil
end
Temp::Service.do_job
end
RSpec: use `receive ... exactly ... with ... and_return ...` with different `with` arguments
There's an rspec-any_of
gem that allows for the following syntax by prodiding all_of
argument matcher:
expect(ctx[:helpers]).to receive(:sanitize_strip).with(
%{String\n<a href="http://localhost:3000/">description</a> <br/>and newline\n<br>}
all_of({length: 15}, {length: nil})
)
.and_return('String descr...', 'String description and newline')
.twice
rspec, validate the actual Expectation parameter
You can use a custom matches in with() as shown in the spec docs https://relishapp.com/rspec/rspec-mocks/docs/setting-constraints/matching-arguments#using-a-custom-matcher
rspec new syntax stub method with parameters and return fix value
This is how the new syntax works:
allow(A).to receive(:next).with(1).and_return("B")
rspec and_return multiple values
Multiple-value returns are arrays:
> def f; return 1, 2; end
> f.class
=> Array
So return an array:
f.stub!(:foo).and_return([3, 56])
Related Topics
Get SASS from Database (Compile Passed Data Instead of Reading from File)
Strip Signatures and Replies from Emails
Ruby Method Calls Declared in Class Body
Can't Install Ffi -V '1.9.18' on MACos Catalina
Jekyll on Windows: Pygments Not Working
When to Call a "Require" in Rails
Seeding File Uploads with Carrierwave, Rails 3
How to Check If a Param Is True or False
Undefined Method 'Devise' for User
Is Every Relavant Calculation Performed Every Time the Page Is Loaded
How to Log Every Method That's Called in a Ruby Program
How to Convert Array of Activerecord Models to CSV
Why Is Safe Navigation Better Than Using Try in Rails