Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stubbing With String or Regex #317

Open
benhamill opened this issue Oct 16, 2013 · 4 comments
Open

Stubbing With String or Regex #317

benhamill opened this issue Oct 16, 2013 · 4 comments

Comments

@benhamill
Copy link

using with with a block seems to behave differently when you pass a regexp versus a string. Example script:

require 'webmock'
require 'faraday'

WebMock.disable_net_connect!

WebMock.stub_request(:get, "http://example.com/fails").with do |request|
  request.uri.query_values['foo'] == 'bar'
end

WebMock.stub_request(:get, %r{http://example\.com/passes}).with do |request|
  request.uri.query_values['foo'] == 'bar'
end

http = Faraday.new("http://example.com")

http.get('/passes?foo=bar')
http.get('/fails?foo=bar')

The output:

❱ ruby webmock_with_test.rb 
/home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/webmock-1.15.0/lib/webmock/http_lib_adapters/net_http.rb:114:in `request': Real HTTP connections are disabled. Unregistered request: GET http://example.com/fails?foo=bar with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Faraday v0.8.8'} (WebMock::NetConnectNotAllowedError)

You can stub this request with the following snippet:

stub_request(:get, "http://example.com/fails?foo=bar").
  with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Faraday v0.8.8'}).
  to_return(:status => 200, :body => "", :headers => {})

registered request stubs:

stub_request(:get, "/http:\/\/example\.com\/passes/")
stub_request(:get, "http://example.com/fails")

============================================================
        from /home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/net/http.rb:1126:in `get'
        from /home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/faraday-0.8.8/lib/faraday/adapter/net_http.rb:73:in `perform_request'
        from /home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/faraday-0.8.8/lib/faraday/adapter/net_http.rb:38:in `call'
        from /home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/faraday-0.8.8/lib/faraday/request/url_encoded.rb:14:in `call'
        from /home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/faraday-0.8.8/lib/faraday/connection.rb:253:in `run_request'
        from /home/ben/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/faraday-0.8.8/lib/faraday/connection.rb:106:in `get'
        from webmock_with_test.rb:17:in `<main>'

Is this intended behavior? If not, shall I see if I can solve it and turn this into a Pull Request?

@benhamill
Copy link
Author

Also note: I realize I could have used with without a block for this example; this is simplified from what I'm actually trying to do for the sake of easy comprehension.

@bblimke
Copy link
Owner

bblimke commented Oct 17, 2013

It was intended, though unfortunate behaviour. Matching requests using with was added later to WebMock.
Early WebMock only matched uri's.

If you are using regexp to match uri, WebMock basically tries match uri string against the regexp. It does it in a robust way, which matches uris with different order of params etc, but that's not relevant.

When you are using string to match uri, WebMock also does it in a robust way, but expects full uri, including params. Early version of WebMock assumed that the only way to match uri is to pass the whole uri to stub. with was added later. It was difficult to change this behaviour without breaking backwards compatibility.
You can pass query param to with method, which will work as a workaround.

It's one of the things that I'd like to change in the next major release of WebMock. Many people were already confuses about this behaviour.

Unfortunately I don't have much time to work on WebMock 2.0 on my own. maybe it's time to move project under github.com/webmock/webmock

@benhamill
Copy link
Author

Yeah. For now, I'm just using regexes when I need to do something dynamic with queries.

Some context: What I need, ideally, is some way to capture a query parameter that my app sends out and make sure that it's used in subsequent requests. Imagine that it's an id value from a SQL table for a new row (and so doesn't exist to predict prior to the test running).

What I'd love to be able to do is something like:

WebMock.stub_request(:post, "http://example.com/resources").with do |request|
  @uid = request.uri.query_values['uid']
  request.uri.query_values.keys.sort == ['uid', 'name']
end
WebMock.stub_request(:get, "http://example.com/resources/#{@uid}/subresources")

...and have the uid thing lazily interpolated... but right now (with regex instead of string), @uid isn't filled until the first request is actually made, so the second stub is set up with nil in there. :(

@kmayer
Copy link

kmayer commented Jun 1, 2016

@benhamill Wrap your ID generator in a class/method that you stub for testing, e.g. UUID generates random UUIDs, but for testing purposes, I stub it out to a static string. Then you know the ID a priori.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants