rspec-expectations
rspec-expectations copied to clipboard
It would be nice to add `.to receive(...).with_block`
There is no easy way to verify a method would be called with a block.
It would be nice to have
expect(thing).to receive(:method).with_block
Hello @ioquatix
This is probably not what you are asking but have you seen? https://github.com/rspec/rspec-expectations/blob/v3.7.0/features/custom_matchers/define_block_matcher.feature
Also, it's funny because factory_bot have a matcher for block with the name you mentioned. https://github.com/thoughtbot/factory_bot/blob/40c8708c473279d3f812a825ff979f2c93451e05/spec/support/matchers/trait.rb
Used like this: https://github.com/thoughtbot/factory_bot/blob/ad107bea15aa75b60decbbebbc86980fd3e85d34/spec/factory_bot/definition_proxy_spec.rb#L127-L130
Bye
@benoittgt I think @ioquatix is talking about receive(...)
from rspec-mocks, so that you can expect to receive a message with a block. You can currently deal with this by passing a block to receive
:
expect(thing).to receive(:method) do |&block|
expect(block).not_to be_nil
end
If we wanted to add more explicit support for this, I'd rather not add a new with_block
API; instead maybe something like:
expect(thing).to receive(:method).with(a_block)
Where a_block
is a "special" argument matcher like any_args
or no_args
that doesn't match on a positional arg but instead rspec-mocks handles internally.
@ioquatix does the approach I suggested above work for you?
Thanks, @myronmarston for clarification. I agree with your proposal.
Yep it would be fine. Does it work with arguments too?
Yep it would be fine. Does it work with arguments too?
I'm not sure what you mean by "work with arguments". Can you provide an example of what you mean?
expect(thing).to receive(:method).with(1, 2, 3, a_block)
it's actually not that important to my use case, just thought it might be useful in the general case.
Hopefully, yes, we could make that work.
Do you want to take a stab at adding it. Improving RSpec is largely a self-service operation unless one of the core team members wants to take this work on (which often doesn't happen; we all have lives and jobs!).
Sure, that makes sense.
If I have time, I will mention here I am starting work. Otherwise, this is free for anyone who is interested to implement it. If someone else picks it up, please mention it here so we don't duplicate effort :)
@myronmarston I've tried taking a stab at this in kaiwren/1065-with-a-block - am able to get this working at the cucumber feature level, but I'm missing something on the sad path spec which I'm unable to get to pass (even though it works fine in the cuke). I'm unable to figure out why I'm not able to catch the exception; probably missing something really obvious...
Would be grateful if I could get a quick review and some feedback. If my approach isn't flawed, will complete this and raise a PR.
Maybe @ioquatix can provide a review too?
https://github.com/kaiwren/rspec-mocks/commit/524637dfe8de2078c58d0683c3a59222940a05ca
It looks pretty good.
I've expanded on @kaiwren's work over on rspec/rspec-mocks#1237, it's worth noting we already had the and_yield
expectation, and I think there are actually a few issues with a_block
, what happens when used positionally? and does it always mean the supplied &block
argument? After all object.msg(proc {}, proc {})
is valid Ruby, should we expect on this with .with(a_block, a_block)
and how do we differentiated that from msg(proc{}) { }
.
Did this ever get merged in? Looking at it 4 years later, and still think it would be useful.
I don't think so!