Skip to content
Olia Kremmyda edited this page Mar 24, 2018 · 2 revisions

Matching requests

An executed request matches stubbed request if it passes following criteria:

  • When request URI matches stubbed request URI string, Regexp pattern or RFC 6570 URI Template
  • And request method is the same as stubbed request method or stubbed request method is :any
  • And request body is the same as stubbed request body or stubbed request body is not specified
  • And request headers match stubbed request headers, or stubbed request headers match a subset of request headers, or stubbed request headers are not specified
  • And request matches provided block or block is not provided

Precedence of stubs

Always the last declared stub matching the request will be applied i.e:

stub_request(:get, "www.example.com").to_return(body: "abc")
stub_request(:get, "www.example.com").to_return(body: "def")

Net::HTTP.get('www.example.com', '/')    # ====> "def"

Matching URIs

WebMock will match all different representations of the same URI.

I.e all the following representations of the URI are equal:

"www.example.com"
"www.example.com/"
"www.example.com:80"
"www.example.com:80/"
"http://www.example.com"
"http://www.example.com/"
"http://www.example.com:80"
"http://www.example.com:80/"

The following URIs with userinfo are also equal for WebMock

"a b:pass@www.example.com"
"a b:pass@www.example.com/"
"a b:pass@www.example.com:80"
"a b:pass@www.example.com:80/"
"http://a b:pass@www.example.com"
"http://a b:pass@www.example.com/"
"http://a b:pass@www.example.com:80"
"http://a b:pass@www.example.com:80/"
"a%20b:pass@www.example.com"
"a%20b:pass@www.example.com/"
"a%20b:pass@www.example.com:80"
"a%20b:pass@www.example.com:80/"
"http://a%20b:pass@www.example.com"
"http://a%20b:pass@www.example.com/"
"http://a%20b:pass@www.example.com:80"
"http://a%20b:pass@www.example.com:80/"

or these

"www.example.com/my path/?a=my param&b=c"
"www.example.com/my%20path/?a=my%20param&b=c"
"www.example.com:80/my path/?a=my param&b=c"
"www.example.com:80/my%20path/?a=my%20param&b=c"
"http://www.example.com/my path/?a=my param&b=c"
"http://www.example.com/my%20path/?a=my%20param&b=c"
"http://www.example.com:80/my path/?a=my param&b=c"
"http://www.example.com:80/my%20path/?a=my%20param&b=c"

If you provide Regexp to match URI, WebMock will try to match it against every valid form of the same url.

I.e /my path/ will match www.example.com/my%20path because it is equivalent of www.example.com/my path

Matching with URI Templates

If you use Addressable::Template for matching, then WebMock will defer the matching rules to Addressable, which complies with RFC 6570.

If you use any of the WebMock methods for matching query params, then Addressable will be used to match the base URI and WebMock will match the query params. If you do not, then WebMock will let Addressable match the full URI.

Matching headers

WebMock will match request headers against stubbed request headers in the following situations:

  1. Stubbed request has headers specified and request headers are the same as stubbed headers
    i.e
    stubbed headers: { 'Header1' => 'Value1', 'Header2' => 'Value2' }, 
          requested: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
    
  2. Stubbed request has headers specified and stubbed request headers are a subset of request headers
    i.e
    stubbed headers: { 'Header1' => 'Value1'  },
          requested: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
    
  3. Stubbed request has no headers
    i.e
    stubbed headers: nil,
          requested: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
    

WebMock normalises headers and treats all forms of same headers as equal
i.e the following two sets of headers are equal:

{ "Header1" => "value1",  content_length:    123,  X_CuStOm_hEAder:    :value  }
{  header1:    "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }