Webmock: Matcher with a block

Created on 9 Apr 2012  ·  6Comments  ·  Source: bblimke/webmock

Please, take a look at this line:

WebMock.should have_requested(:post, "www.example.com").with { |req| req.body == "abc" }

The code in the block will never be executed. I tried to raise an error there, tests passed.

I used:

Ruby 1.9.2
Webmock 1.8.6
Rspec 2.8.0
CurbFu 0.6.1
Curb 0.8.0

Most helpful comment

Hi Ben.

It's not a problem with WebMock, but with Ruby semantics.

Your code is going to work fine if you replace do..end with {}
do..end has weaker binding than curly brackets.

Due to weaker binding of do end, your code is interpreted by Ruby in the following way (please note the parethesis):

expect(WebMock).to(have_requested(
  :post,
  "http://benhamill.com/foo"
).with) do |request|
  raise "FAIL!"
end

To fix it you can either replace do..end with {} or add parenthesis to to(...) invocation.

All 6 comments

Can you provide an example spec, which doesn't work (request + expectation)?

No feedback.

I just hit this. Here you go:

● src ❱ gem list rspec webmock faraday
/home/ben/.rbenv/versions/2.1.0/bin/ruby: warning: RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead.

*** LOCAL GEMS ***

rspec (2.14.1)
rspec-core (2.14.7)
rspec-expectations (2.14.4)
rspec-mocks (2.14.4)

*** LOCAL GEMS ***

webmock (1.17.1, 1.16.1)

*** LOCAL GEMS ***

faraday (0.8.8)
faraday_middleware (0.9.0)
● src ❱ ruby --version
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-linux]
● src ❱ cat webmock_with_bug.rb 
require 'rspec'
require 'webmock/rspec'
require 'faraday'

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.syntax = :expect
  end

  config.formatter = :documentation
end

WebMock.disable_net_connect!

describe "have_requested().with" do
  before do
    WebMock.stub_request(
      :post,
      "http://benhamill.com/foo"
    )

    Faraday.post("http://benhamill.com/foo")
  end

  it "never fires the block" do
    expect(WebMock).to have_requested(
      :post,
      "http://benhamill.com/foo"
    ).with do |request|
      raise "FAIL!"
    end
  end
end
● src ❱ rspec webmock_with_bug.rb 
ruby: warning: RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead.

have_requested().with
  never fires the block

Finished in 0.00529 seconds
1 example, 0 failures

What else can I do to help track this down?

Also, sorry for the necromancy... seemed better than starting a new Issue.

Hi Ben.

It's not a problem with WebMock, but with Ruby semantics.

Your code is going to work fine if you replace do..end with {}
do..end has weaker binding than curly brackets.

Due to weaker binding of do end, your code is interpreted by Ruby in the following way (please note the parethesis):

expect(WebMock).to(have_requested(
  :post,
  "http://benhamill.com/foo"
).with) do |request|
  raise "FAIL!"
end

To fix it you can either replace do..end with {} or add parenthesis to to(...) invocation.

OH! Dang. Good catch! Thanks! Also, hopefully others who run into this will see this and be able to work it out. Precedence is hard.

Yes, it's a tricky issue to figure out. I could add a warning to WebMock's README perhaps.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Morred picture Morred  ·  14Comments

leifg picture leifg  ·  19Comments

joallard picture joallard  ·  4Comments

majioa picture majioa  ·  4Comments

vangberg picture vangberg  ·  3Comments