### Complete Test Example Source: https://context7.com/bblimke/webmock/llms.txt A basic setup template for integrating WebMock with RSpec and JSON handling. ```ruby require 'webmock/rspec' require 'net/http' require 'json' ``` -------------------------------- ### Install WebMock Source: https://github.com/bblimke/webmock/blob/master/README.md Installation commands for the WebMock gem. ```bash gem install webmock ``` ```ruby # add to your Gemfile group :test do gem "webmock" end ``` ```bash git clone http://github.com/bblimke/webmock.git cd webmock rake install ``` -------------------------------- ### Install WebMock Source: https://context7.com/bblimke/webmock/llms.txt Add the gem to your Gemfile within the test group. ```ruby # Gemfile group :test do gem "webmock" end ``` -------------------------------- ### Configure Test Frameworks Source: https://context7.com/bblimke/webmock/llms.txt Integration setup for various Ruby testing frameworks. ```ruby # spec/spec_helper.rb require 'webmock/rspec' # WebMock automatically disables external requests in RSpec # and resets stubs between examples ``` ```ruby # test/test_helper.rb require 'webmock/minitest' ``` ```ruby # test/test_helper.rb require 'webmock/test_unit' ``` ```ruby # features/support/webmock.rb require 'webmock/cucumber' ``` -------------------------------- ### Configure WebMock for Test Frameworks Source: https://github.com/bblimke/webmock/blob/master/README.md Integration setup for various Ruby testing frameworks. ```ruby require 'webmock/cucumber' ``` ```ruby require 'webmock/minitest' ``` ```ruby require 'webmock/rspec' ``` ```ruby require 'webmock/test_unit' ``` -------------------------------- ### Assert Stubbed Request Was Made Source: https://github.com/bblimke/webmock/wiki/Test::Unit-support Stub GET and POST requests to www.example.com. Make a GET request and then assert that the stubbed GET request was made, while the stubbed POST request was not. ```ruby stub_get = stub_request(:get, "www.example.com") stub_post = stub_request(:post, "www.example.com") Net::HTTP.get('www.example.com', '/') assert_requested(stub_get) assert_not_requested(stub_post) ``` -------------------------------- ### Header Matching Scenarios Source: https://github.com/bblimke/webmock/wiki/Matching Examples of how WebMock evaluates request headers against stubbed expectations. ```text stubbed headers: { 'Header1' => 'Value1', 'Header2' => 'Value2' }, requested: { 'Header1' => 'Value1', 'Header2' => 'Value2' } ``` ```text stubbed headers: { 'Header1' => 'Value1' }, requested: { 'Header1' => 'Value1', 'Header2' => 'Value2' } ``` ```text stubbed headers: nil, requested: { 'Header1' => 'Value1', 'Header2' => 'Value2' } ``` -------------------------------- ### Create Stub and Make Request Source: https://context7.com/bblimke/webmock/llms.txt Define a stub for a GET request to a specific URL and then make the request using Net::HTTP. The stub will intercept the request. ```ruby stub_request(:get, "https://api.example.com/data"). to_return(body: "response") Net::HTTP.get(URI("https://api.example.com/data")) ``` -------------------------------- ### Enable Net::HTTP Connections on Start Source: https://github.com/bblimke/webmock/blob/master/README.md This option forces the WebMock Net::HTTP adapter to always connect on `Net::HTTP.start`. All connections are allowed by default. To enable connections only to a specific domain, pass the domain as an argument. ```ruby WebMock.allow_net_connect!(net_http_connect_on_start: true) ``` ```ruby WebMock.allow_net_connect!(net_http_connect_on_start: "www.example.com") ``` -------------------------------- ### Expecting Real (Not Stubbed) Requests in Test::Unit Source: https://github.com/bblimke/webmock/blob/master/README.md This example shows how to allow all network connections and then assert that a real request was made. This is useful for testing interactions with external services when stubbing is not desired. ```ruby WebMock.allow_net_connect! Net::HTTP.get('www.example.com', '/') # ===> Success assert_requested :get, "http://www.example.com" # ===> Success ``` -------------------------------- ### Stub HTTP Requests Source: https://github.com/bblimke/webmock/blob/master/README.md Examples of stubbing requests based on URI, method, body, and headers. ```ruby stub_request(:any, "www.example.com") Net::HTTP.get("www.example.com", "/") # ===> Success ``` ```ruby stub_request(:post, "www.example.com"). with(body: "abc", headers: { 'Content-Length' => 3 }) uri = URI.parse("http://www.example.com/") req = Net::HTTP::Post.new(uri.path) req['Content-Length'] = 3 res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, "abc") end # ===> Success ``` ```ruby stub_request(:post, "www.example.com"). with(body: /world$/, headers: {"Content-Type" => /image\/.+/}). to_return(body: "abc") uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Content-Type'] = 'image/png' res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'hello world') end # ===> Success ``` ```ruby stub_request(:post, "www.example.com"). with(body: {data: {a: '1', b: 'five'}}) RestClient.post('www.example.com', "data[a]=1&data[b]=five", content_type: 'application/x-www-form-urlencoded') # ===> Success RestClient.post('www.example.com', '{"data":{"a":"1","b":"five"}}', content_type: 'application/json') # ===> Success RestClient.post('www.example.com', '', content_type: 'application/xml') # ===> Success ``` ```ruby stub_request(:post, "www.example.com"). with(body: hash_including({data: {a: '1', b: 'five'}})) RestClient.post('www.example.com', "data[a]=1&data[b]=five&x=1", :content_type => 'application/x-www-form-urlencoded') # ===> Success ``` -------------------------------- ### Define User API Client in Ruby Source: https://context7.com/bblimke/webmock/llms.txt A simple Ruby class to interact with a User API, including methods for getting and creating users. Requires Net::HTTP and JSON libraries. ```ruby class UserAPIClient BASE_URL = "https://api.example.com" def self.get_user(id) uri = URI("#{BASE_URL}/users/#{id}") response = Net::HTTP.get_response(uri) case response.code when "200" JSON.parse(response.body) when "404" nil else raise "API Error: #{response.code}" end end def self.create_user(name:, email:) uri = URI("#{BASE_URL}/users") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri.path) request['Content-Type'] = 'application/json' request.body = { name: name, email: email }.to_json response = http.request(request) JSON.parse(response.body) end end ``` -------------------------------- ### Stub and Assert HTTP Requests with Test::Unit Source: https://github.com/bblimke/webmock/wiki/Test::Unit-support Stub a request to www.example.com and then assert that a specific POST request was made with certain headers and body. Also asserts that a GET request to another domain was not made. ```ruby require 'webmock/test_unit' stub_request(:any, "www.example.com") uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Content-Length'] = 3 res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'abc') end assert_requested :post, "http://www.example.com", headers: {'Content-Length' => 3}, body: "abc", times: 1 # ===> Success assert_not_requested :get, "http://www.something.com" # ===> Success assert_requested(:post, "http://www.example.com", times: 1) { |req| req.body == "abc" } ``` -------------------------------- ### Allow Real Network Connections Source: https://github.com/bblimke/webmock/wiki/Test::Unit-support Temporarily allow WebMock to permit real network connections. Useful for testing scenarios where external services are required. Asserts that a GET request was made. ```ruby WebMock.allow_net_connect! Net::HTTP.get('www.example.com', '/') # ===> Success assert_requested(:get, "http://www.example.com") # ===> Success ``` -------------------------------- ### Setting Expectations in RSpec on WebMock Module Source: https://github.com/bblimke/webmock/blob/master/README.md This example shows how to set expectations for HTTP requests using WebMock within an RSpec test suite, using the `expect` syntax and matching request details like body and headers. ```ruby require 'webmock/rspec' expect(WebMock).to have_requested(:get, "www.example.com"). with(body: "abc", headers: {'Content-Length' => 3}).twice expect(WebMock).not_to have_requested(:get, "www.something.com") expect(WebMock).to have_requested(:post, "www.example.com"). with { |req| req.body == "abc" } # Note that the block with `do ... end` instead of curly brackets won't work! ``` -------------------------------- ### Define request callbacks in WebMock Source: https://github.com/bblimke/webmock/blob/master/README.md Use after_request to hook into request completion. The second example demonstrates filtering by request type and library. ```ruby WebMock.after_request do |request_signature, response| puts "Request #{request_signature} was made and #{response} was returned" end ``` ```ruby WebMock.after_request(except: [:patron], real_requests_only: true) do |req_signature, response| puts "Request #{req_signature} was made and #{response} was returned" end ``` -------------------------------- ### Stub Request with Additional Headers Source: https://context7.com/bblimke/webmock/llms.txt Stub a GET request to return a JSON response with custom headers. ```ruby stub_request(:get, "https://api.example.com/items"). to_return_json( status: 200, body: { items: [{ id: 1 }, { id: 2 }], total: 2 }, headers: { 'X-Total-Count' => '2' } ) ``` -------------------------------- ### Stub GET request for user data in RSpec Source: https://context7.com/bblimke/webmock/llms.txt Use WebMock's stub_request to simulate a successful GET request for a user. Ensures the API client correctly parses JSON responses and verifies the request was made. ```ruby stub_request(:get, "https://api.example.com/users/123"). to_return_json(body: { id: 123, name: "John Doe", email: "john@example.com" }) user = UserAPIClient.get_user(123) expect(user).to eq({ "id" => 123, "name" => "John Doe", "email" => "john@example.com" }) expect(a_request(:get, "https://api.example.com/users/123")).to have_been_made.once ``` -------------------------------- ### Enable WebMock Globally Source: https://github.com/bblimke/webmock/wiki/Enabling-and-Disabling-WebMock Use `WebMock.enable!` to activate WebMock for all supported HTTP client adapters. ```ruby WebMock.enable! ``` -------------------------------- ### Basic Response Configuration with `to_return` Source: https://context7.com/bblimke/webmock/llms.txt Configure static responses including status code, body content, and headers. Ensure correct `Content-Type` for JSON responses. ```ruby require 'webmock/rspec' require 'net/http' # Basic response with body, status, and headers stub_request(:get, "https://api.example.com/user"). to_return( status: 200, body: '{"id": 1, "name": "John Doe"}', headers: { 'Content-Type' => 'application/json', 'X-Request-Id' => 'abc123' } ) ``` -------------------------------- ### Manage network connectivity settings Source: https://github.com/bblimke/webmock/blob/master/README.md Toggle global network access and configure exceptions for local connections. ```ruby WebMock.allow_net_connect! stub_request(:any, "www.example.com").to_return(body: "abc") Net::HTTP.get('www.example.com', '/') # ===> "abc" Net::HTTP.get('www.something.com', '/') # ===> /.+Something.+/ WebMock.disable_net_connect! Net::HTTP.get('www.something.com', '/') # ===> Failure ``` ```ruby WebMock.disable_net_connect!(allow_localhost: true) Net::HTTP.get('www.something.com', '/') # ===> Failure Net::HTTP.get('localhost:9887', '/') # ===> Allowed. Perhaps to Selenium? ``` -------------------------------- ### Stub request timeout in RSpec Source: https://context7.com/bblimke/webmock/llms.txt Simulate a network timeout for a GET request. Verifies that the API client handles timeouts by raising a Timeout::Error. ```ruby stub_request(:get, "https://api.example.com/users/1").to_timeout expect { UserAPIClient.get_user(1) }.to raise_error(Timeout::Error) ``` -------------------------------- ### Toggle network connections Source: https://github.com/bblimke/webmock/wiki/Real-request-handling Enable or disable all real network connections globally. ```ruby WebMock.allow_net_connect! stub_request(:any, "www.example.com").to_return(body: "abc") Net::HTTP.get('www.example.com', '/') # ===> "abc" Net::HTTP.get('www.something.com', '/') # ===> /.+Something.+/ WebMock.disable_net_connect! Net::HTTP.get('www.something.com', '/') # ===> Failure ``` -------------------------------- ### Stub 404 Not Found response in RSpec Source: https://context7.com/bblimke/webmock/llms.txt Simulate a 404 Not Found HTTP response for a GET request. Verifies that the API client correctly returns nil when a user is not found. ```ruby stub_request(:get, "https://api.example.com/users/999"). to_return(status: 404, body: '{"error": "Not found"}') expect(UserAPIClient.get_user(999)).to be_nil ``` -------------------------------- ### Create Request Patterns Source: https://github.com/bblimke/webmock/wiki/WebMock-API Methods to define patterns for matching HTTP requests. ```ruby a_request(method, uri) request(method, uri) ``` -------------------------------- ### Match body and headers with regex Source: https://github.com/bblimke/webmock/wiki/Stubbing Use regular expressions to match request bodies and header values. ```ruby stub_request(:post, "www.example.com"). with(body: /world$/, headers: {"Content-Type" => /image\/.+/}). to_return(body: "abc") uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Content-Type'] = 'image/png' res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'hello world') end # ===> Success ``` -------------------------------- ### Respond with Rack Application Source: https://context7.com/bblimke/webmock/llms.txt Delegates request handling to a Rack application. Useful for complex response logic or testing against real Rack applications. Can be used with Sinatra or other Rack apps. ```ruby require 'webmock/rspec' require 'net/http' # Simple Rack app class SimpleRackApp def self.call(env) [200, { 'Content-Type' => 'text/plain' }, ['Hello from Rack!']] end end stub_request(:any, "https://api.example.com").to_rack(SimpleRackApp) Net::HTTP.get(URI("https://api.example.com/")) # => "Hello from Rack!" ``` ```ruby # Rack app that echoes request info class EchoApp def self.call(env) body = { method: env['REQUEST_METHOD'], path: env['PATH_INFO'], query: env['QUERY_STRING'] }.to_json [200, { 'Content-Type' => 'application/json' }, [body]] end end stub_request(:any, /echo.example.com/).to_rack(EchoApp) ``` ```ruby # Use with Sinatra or other Rack apps # stub_request(:any, "https://api.example.com").to_rack(MyRailsApp) # stub_request(:any, "https://api.example.com").to_rack(MySinatraApp) ``` -------------------------------- ### Header Normalization Source: https://github.com/bblimke/webmock/wiki/Matching WebMock treats different header key formats as equivalent. ```ruby { "Header1" => "value1", content_length: 123, X_CuStOm_hEAder: :value } { header1: "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" } ``` -------------------------------- ### Stub 500 Internal Server Error response in RSpec Source: https://context7.com/bblimke/webmock/llms.txt Simulate a 500 Internal Server Error response for a GET request. Ensures that the API client raises an appropriate error when the server fails. ```ruby stub_request(:get, "https://api.example.com/users/1"). to_return(status: 500, body: 'Internal Server Error') expect { UserAPIClient.get_user(1) }.to raise_error("API Error: 500") ``` -------------------------------- ### Allow via array of rules Source: https://github.com/bblimke/webmock/wiki/Real-request-handling Pass an array containing strings, regexps, or callables to define multiple allowed network paths. ```ruby WebMock.disable_net_connect!(allow: [ lambda{|uri| uri.host.length % 2 == 0 }, /ample.org/, 'bbc.co.uk', ]) RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('bbc.co.uk', '/') # ===> Allowed RestClient.get('bbc.com', '/') # ===> Allowed RestClient.get('www.bbc.com', '/') # ===> Failure ``` -------------------------------- ### Response Body from File Source: https://context7.com/bblimke/webmock/llms.txt Serve responses directly from a file by passing a `File` object to the `body` argument. This is useful for large or complex response bodies. ```ruby # Response body from file stub_request(:get, "https://api.example.com/large-data"). to_return( status: 200, body: File.new('spec/fixtures/response.json'), headers: { 'Content-Type' => 'application/json' } ) ``` -------------------------------- ### Register Global Request Stubs Source: https://context7.com/bblimke/webmock/llms.txt Configure global stubs that apply to all requests, with options to set precedence before or after local stubs. ```ruby require 'webmock/rspec' require 'net/http' # Global stub applied BEFORE local stubs (default) WebMock.globally_stub_request do |request| if request.uri.host == 'metrics.example.com' { status: 200, body: 'tracked' } end # Return nil to let other stubs handle end # Global stub applied AFTER local stubs WebMock.globally_stub_request(:after_local_stubs) do |request| # Fallback for any unmatched request { status: 404, body: 'Not Found' } end # Use case: Default responses for monitoring/analytics WebMock.globally_stub_request do |request| case request.uri.host when 'analytics.google.com' { status: 200, body: '' } when 'sentry.io' { status: 200, body: '{"id": "event123"}' } end end # Local stub takes precedence (when global is :before_local_stubs) stub_request(:get, "https://api.example.com/specific"). to_return(body: "specific response") Net::HTTP.get(URI("https://api.example.com/specific")) # => "specific response" Net::HTTP.get(URI("https://api.example.com/other")) # => "Not Found" (global fallback) ``` -------------------------------- ### Enable WebMock Except Specific Adapters Source: https://github.com/bblimke/webmock/wiki/Enabling-and-Disabling-WebMock Use `WebMock.enable!(except: [:adapter_name])` to enable WebMock for all adapters except the ones specified in the `except` array. ```ruby WebMock.enable!(except: [:patron]) ``` -------------------------------- ### Match partial query parameters Source: https://github.com/bblimke/webmock/wiki/Stubbing Use hash_including to match a subset of query parameters. ```ruby stub_request(:get, "www.example.com"). with(query: hash_including({"a" => ["b", "c"]})) RestClient.get("http://www.example.com/?a[]=b&a[]=c&x=1") # ===> Success ``` -------------------------------- ### Equivalent URI Representations Source: https://github.com/bblimke/webmock/wiki/Matching WebMock treats various URI formats as equivalent for matching purposes. ```ruby "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/" ``` ```ruby "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/" ``` ```ruby "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" ``` -------------------------------- ### Allow URI via Regexp Source: https://github.com/bblimke/webmock/wiki/Real-request-handling Use a regular expression to define allowed URI patterns. ```ruby WebMock.disable_net_connect!(allow: %r{ample.org/foo}) RestClient.get('www.example.org', '/foo/bar') # ===> Allowed RestClient.get('sample.org', '/foo') # ===> Allowed RestClient.get('sample.org', '/bar') # ===> Failure ``` -------------------------------- ### Stub request by method, URI, body, and headers Source: https://github.com/bblimke/webmock/wiki/Stubbing Define specific criteria for matching requests including body content and header values. ```ruby stub_request(:post, "www.example.com"). with(body: "abc", headers: { 'Content-Length' => 3 }) uri = URI.parse("http://www.example.com/") req = Net::HTTP::Post.new(uri.path) req['Content-Length'] = 3 res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, "abc") end # ===> Success ``` -------------------------------- ### Match URIs with RFC 6570 templates Source: https://github.com/bblimke/webmock/wiki/Stubbing Use Addressable::Template to match URIs based on RFC 6570. ```ruby uri_template = Addressable::Template.new "www.example.com/{id}/" stub_request(:any, uri_template) Net::HTTP.get('www.example.com', '/webmock/') # ===> Success ``` ```ruby uri_template = Addressable::Template.new "www.example.com/thing/{id}.json{?x,y,z}{&other*}" stub_request(:any, uri_template) Net::HTTP.get('www.example.com', '/thing/5.json?x=1&y=2&z=3&anyParam=4') # ===> Success ``` -------------------------------- ### Stub requests with file-based dynamic responses Source: https://github.com/bblimke/webmock/blob/master/README.md Load response content from a file dynamically based on the request host. ```bash curl -is www.example.com > /tmp/www.example.com.txt ``` ```ruby stub_request(:get, "www.example.com"). to_return(lambda { |request| File.new("/tmp/#{request.uri.host.to_s}.txt") }) ``` -------------------------------- ### Stub HTTP Requests Source: https://context7.com/bblimke/webmock/llms.txt Create request stubs for specific methods and URIs, optionally configuring custom responses. ```ruby require 'webmock/rspec' require 'net/http' # Basic stub - matches any request to the URI stub_request(:any, "www.example.com") Net::HTTP.get("www.example.com", "/") # => "" (empty body, 200 status) # Stub specific HTTP method stub_request(:get, "https://api.example.com/users") stub_request(:post, "https://api.example.com/users") stub_request(:put, "https://api.example.com/users/1") stub_request(:delete, "https://api.example.com/users/1") stub_request(:patch, "https://api.example.com/users/1") # Stub with custom response stub_request(:get, "https://api.example.com/users"). to_return( status: 200, body: '[{"id": 1, "name": "John"}]', headers: { 'Content-Type' => 'application/json' } ) uri = URI("https://api.example.com/users") response = Net::HTTP.get_response(uri) response.code # => "200" response.body # => '[{"id": 1, "name": "John"}]' response['Content-Type'] # => "application/json" ``` -------------------------------- ### with - Request Matching Source: https://context7.com/bblimke/webmock/llms.txt Specifies conditions that requests must match, including headers, body content, query parameters, and basic authentication. ```APIDOC ## with ### Description Specifies conditions that requests must match including headers, body content, query parameters, and basic authentication. Supports exact matching, regular expressions, partial hash matching, and custom blocks. ### Parameters #### Request Body - **headers** (Hash) - Optional - Headers to match - **body** (Hash/Regexp) - Optional - Body content to match - **query** (Hash) - Optional - Query parameters to match - **basic_auth** (Array) - Optional - Basic authentication credentials [username, password] ### Request Example stub_request(:post, "https://api.example.com/users").with(body: { name: "John", email: "john@example.com" }, headers: { 'Content-Type' => 'application/json' }).to_return(status: 201, body: '{"id": 1}') ``` -------------------------------- ### Stubbing with custom response Source: https://github.com/bblimke/webmock/blob/master/README.md Define the response body, status, and headers using the to_return method. ```ruby stub_request(:any, "www.example.com"). to_return(body: "abc", status: 200, headers: { 'Content-Length' => 3 }) Net::HTTP.get("www.example.com", '/') # ===> "abc" ``` ```ruby stub_request(:any, "www.example.com").to_return body: '{}', headers: {content_type: 'application/json'} ``` -------------------------------- ### Allow specific host and port Source: https://github.com/bblimke/webmock/wiki/Real-request-handling Restrict network access to a specific host and port combination. ```ruby WebMock.disable_net_connect!(allow: 'www.example.org:8080') RestClient.get('www.something.com', '/') # ===> Failure RestClient.get('www.example.org', '/') # ===> Failure RestClient.get('www.example.org:8080', '/') # ===> Allowed ``` -------------------------------- ### Match URIs with regex Source: https://github.com/bblimke/webmock/wiki/Stubbing Use regular expressions to match dynamic URI patterns. ```ruby stub_request(:any, /example/) Net::HTTP.get('www.example.com', '/') # ===> Success ``` -------------------------------- ### Match requests with a block Source: https://github.com/bblimke/webmock/wiki/Stubbing Use a block to perform custom logic for request matching. ```ruby stub_request(:post, "www.example.com").with { |request| request.body == "abc" } RestClient.post('www.example.com', 'abc') # ===> Success ``` -------------------------------- ### Stub basic authentication in URL Source: https://github.com/bblimke/webmock/wiki/Stubbing Include credentials directly within the stubbed URL. ```ruby stub_request(:get, "user:pass@www.example.com") RestClient.get('user:pass@www.example.com') # ===> Success ``` -------------------------------- ### Match multiple headers with same name Source: https://github.com/bblimke/webmock/wiki/Stubbing Match headers that contain multiple values by providing an array. ```ruby stub_request(:get, 'www.example.com'). with(headers: {'Accept' => ['image/jpeg', 'image/png'] }) req = Net::HTTP::Get.new("/") req['Accept'] = ['image/png'] req.add_field('Accept', 'image/jpeg') Net::HTTP.start("www.example.com") {|http| http.request(req) } # ===> Success ``` -------------------------------- ### Match query parameters with hash Source: https://github.com/bblimke/webmock/wiki/Stubbing Match specific query parameters using a hash structure. ```ruby stub_request(:get, "www.example.com").with(query: {"a" => ["b", "c"]}) RestClient.get("http://www.example.com/?a[]=b&a[]=c") # ===> Success ``` -------------------------------- ### Dynamic Response Body with Lambda Source: https://context7.com/bblimke/webmock/llms.txt Use a lambda to dynamically generate the response body. The lambda receives the request object and should return the body content as a string. ```ruby # Dynamic response with lambda for body only stub_request(:get, /\/users\/\d+/). to_return( status: 200, body: lambda { |request| user_id = request.uri.path.split('/').last %Q({"id": #{user_id}, "name": "User #{user_id}"}) } ) ``` -------------------------------- ### Sequence multiple responses for repeated requests Source: https://github.com/bblimke/webmock/blob/master/README.md Provide multiple responses that are returned in order for subsequent requests. ```ruby stub_request(:get, "www.example.com"). to_return({body: "abc"}, {body: "def"}) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" #after all responses are used the last response will be returned infinitely Net::HTTP.get('www.example.com', '/') # ===> "def\n" ``` ```ruby stub_request(:get, "www.example.com"). to_return({body: "abc"}).then. #then() is just a syntactic sugar to_return({body: "def"}).then. to_raise(MyException) Net::HTTP.get('www.example.com', '/') # ===> "abc\n" Net::HTTP.get('www.example.com', '/') # ===> "def\n" Net::HTTP.get('www.example.com', '/') # ===> MyException raised ``` -------------------------------- ### Match Request Conditions Source: https://context7.com/bblimke/webmock/llms.txt Define matching criteria for requests including headers, body content, query parameters, and authentication. ```ruby require 'webmock/rspec' require 'net/http' require 'json' # Match request with specific headers stub_request(:get, "https://api.example.com/data"). with(headers: { 'Authorization' => 'Bearer token123', 'Accept' => 'application/json' }). to_return(status: 200, body: '{"data": "secret"}') # Match request with body (works with JSON, XML, or URL-encoded) stub_request(:post, "https://api.example.com/users"). with( body: { name: "John", email: "john@example.com" }, headers: { 'Content-Type' => 'application/json' } ). to_return(status: 201, body: '{"id": 1}') # Match with regular expressions stub_request(:post, "https://api.example.com/logs"). with(body: /error/i, headers: { 'Content-Type' => /text\/.+/ }). to_return(status: 200) # Match partial body using hash_including stub_request(:post, "https://api.example.com/search"). with(body: hash_including({ query: "ruby" })). to_return(status: 200, body: '{"results": []}') # Match query parameters stub_request(:get, "https://api.example.com/search"). with(query: { q: "webmock", page: "1" }). to_return(status: 200, body: '{"results": ["WebMock gem"]}') # Match partial query params stub_request(:get, "https://api.example.com/items"). with(query: hash_including({ category: "books" })). to_return(status: 200, body: '[]') # Exclude certain query params stub_request(:get, "https://api.example.com/public"). with(query: hash_excluding({ admin: "true" })). to_return(status: 200) # Match basic authentication stub_request(:get, "https://api.example.com/protected"). with(basic_auth: ['username', 'password']). to_return(status: 200, body: 'Welcome!') ``` -------------------------------- ### Request Patterns Source: https://github.com/bblimke/webmock/wiki/WebMock-API Methods to create request patterns for matching. ```APIDOC ## Create new pattern ### Description Creates a request pattern object. ### Methods - a_request(method, uri) - request(method, uri) ``` -------------------------------- ### Match custom request headers Source: https://github.com/bblimke/webmock/wiki/Stubbing Stub requests based on specific custom header keys and values. ```ruby stub_request(:any, "www.example.com"). with(headers:{ 'Header-Name' => 'Header-Value' }) uri = URI.parse('http://www.example.com/') req = Net::HTTP::Post.new(uri.path) req['Header-Name'] = 'Header-Value' res = Net::HTTP.start(uri.host, uri.port) do |http| http.request(req, 'abc') end # ===> Success ``` -------------------------------- ### stub_request Source: https://context7.com/bblimke/webmock/llms.txt Creates a stub for HTTP requests matching the specified method and URI, allowing for custom response configuration. ```APIDOC ## stub_request ### Description Creates a stub for HTTP requests matching the specified method and URI. Returns a RequestStub object that can be chained with .with() for matching conditions and .to_return() for response configuration. ### Method GET, POST, PUT, DELETE, PATCH, ANY ### Parameters #### Path Parameters - **method** (Symbol) - Required - The HTTP method to stub (e.g., :get, :post, :any) - **uri** (String) - Required - The URI to match ### Request Example stub_request(:get, "https://api.example.com/users").to_return(status: 200, body: '[{"id": 1, "name": "John"}]', headers: { 'Content-Type' => 'application/json' }) ### Response #### Success Response (200) - **status** (Integer) - HTTP status code - **body** (String) - Response body content - **headers** (Hash) - Response headers ``` -------------------------------- ### Use WebMock Outside a Test Framework Source: https://github.com/bblimke/webmock/blob/master/README.md Manual activation of WebMock for non-test environments. ```ruby require 'webmock' include WebMock::API WebMock.enable! ``` -------------------------------- ### Register after_request Callbacks Source: https://context7.com/bblimke/webmock/llms.txt Define callbacks to execute after HTTP requests, useful for logging, debugging, or collecting request data for custom assertions. ```ruby require 'webmock/rspec' require 'net/http' # Log all requests WebMock.after_request do |request_signature, response| puts "Request: #{request_signature.method.upcase} #{request_signature.uri}" puts "Response: #{response.status.first} - #{response.body[0..100]}" end # Only log real requests (not stubbed) WebMock.after_request(real_requests_only: true) do |request, response| puts "Real request made to: #{request.uri}" end # Exclude specific libraries WebMock.after_request(except: [:patron]) do |request, response| # Called for all libraries except Patron end # Collect requests for custom assertions recorded_requests = [] WebMock.after_request do |request, response| recorded_requests << { method: request.method, uri: request.uri.to_s, body: request.body, status: response.status.first } end # Make requests stub_request(:any, /example\.com/) Net::HTTP.get(URI("http://example.com/api")) Net::HTTP.post(URI("http://example.com/data"), "test") # Analyze recorded requests puts recorded_requests.length # => 2 # Reset callbacks WebMock.reset_callbacks ``` -------------------------------- ### WebMock Request Expectations Source: https://github.com/bblimke/webmock/blob/master/README.md Use these matchers to assert that specific HTTP requests have been made. They allow for detailed matching of request parameters. ```ruby expect(WebMock).to have_requested(:get, "www.example.com"). with(query: {"a" => ["b", "c"]}) ``` ```ruby expect(WebMock).to have_requested(:get, "www.example.com"). with(query: hash_including({"a" => ["b", "c"]})) ``` ```ruby expect(WebMock).to have_requested(:get, "www.example.com"). with(body: {"a" => ["b", "c"]}, headers: {'Content-Type' => 'application/json'}) ``` -------------------------------- ### Simulate Exceptions with to_raise Source: https://context7.com/bblimke/webmock/llms.txt Simulates exceptions being raised during HTTP requests. Useful for testing error handling and retry logic. Can raise by class, custom error message, or string. ```ruby require 'webmock/rspec' require 'net/http' # Raise exception by class stub_request(:get, "https://api.example.com/error"). to_raise(StandardError) begin Net::HTTP.get(URI("https://api.example.com/error")) rescue StandardError => e puts "Caught: #{e.class}" # => Caught: StandardError end ``` ```ruby # Raise with custom error message stub_request(:get, "https://api.example.com/not-found"). to_raise(StandardError.new("Resource not found")) ``` ```ruby # Raise by string (creates StandardError) stub_request(:get, "https://api.example.com/fail"). to_raise("Connection failed") ``` ```ruby # Custom exception class class APIError < StandardError; end stub_request(:get, "https://api.example.com/api-error"). to_raise(APIError.new("API rate limit exceeded")) ``` ```ruby # Chain with normal responses for retry testing stub_request(:get, "https://api.example.com/flaky"). to_raise(Errno::ECONNREFUSED).then. to_raise(Errno::ECONNREFUSED).then. to_return(status: 200, body: 'Success after retries') ``` -------------------------------- ### Stub POST request for user creation in RSpec Source: https://context7.com/bblimke/webmock/llms.txt Simulate a POST request to create a user, including request body and headers. Verifies that the API client correctly sends data and receives a successful response. ```ruby stub_request(:post, "https://api.example.com/users"). with( body: { name: "Jane", email: "jane@example.com" }.to_json, headers: { 'Content-Type' => 'application/json' } ). to_return_json(status: 201, body: { id: 456, name: "Jane", email: "jane@example.com" }) result = UserAPIClient.create_user(name: "Jane", email: "jane@example.com") expect(result["id"]).to eq(456) expect(WebMock).to have_requested(:post, "https://api.example.com/users"). with(body: hash_including("name" => "Jane")) ``` -------------------------------- ### Assert Request Execution Source: https://github.com/bblimke/webmock/wiki/WebMock-API Methods to verify if a request was made or not made. ```ruby assert_requested(method_and_options, block) ``` ```ruby assert_not_requested(method_and_options, block) refute_requested(method_and_options, block) ``` -------------------------------- ### URI Matching Patterns in WebMock Source: https://context7.com/bblimke/webmock/llms.txt WebMock supports matching URIs using strings, regular expressions, RFC 6570 URI templates, or lambda functions. It automatically normalizes URIs for equivalent matching. ```ruby require 'webmock/rspec' require 'addressable/template' # String matching - all these are equivalent stub_request(:get, "www.example.com") stub_request(:get, "http://www.example.com") stub_request(:get, "http://www.example.com:80") stub_request(:get, "http://www.example.com/") ``` ```ruby # Regular expression matching stub_request(:get, /example\.com\/api\/v\d+/) Net::HTTP.get(URI("http://example.com/api/v1/users")) # => matches Net::HTTP.get(URI("http://example.com/api/v2/items")) # => matches ``` ```ruby # RFC 6570 URI Template matching uri_template = Addressable::Template.new("https://api.example.com/users/{id}") stub_request(:get, uri_template).to_return(status: 200, body: '{"found": true}') Net::HTTP.get(URI("https://api.example.com/users/123")) # => matches Net::HTTP.get(URI("https://api.example.com/users/456")) # => matches ``` ```ruby # Advanced URI template with query parameters template = Addressable::Template.new("https://api.example.com/search{?q,page,limit}") stub_request(:get, template).to_return(status: 200) Net::HTTP.get(URI("https://api.example.com/search?q=test&page=1&limit=10")) # => matches ``` ```ruby # Lambda/Proc matching for custom logic stub_request(:get, ->(uri) { uri.host.end_with?('.example.com') }). to_return(status: 200, body: 'Matched!') ``` ```ruby # URI with credentials in userinfo stub_request(:get, "user:pass@secure.example.com/data"). to_return(status: 200, body: 'Authenticated') ``` -------------------------------- ### Stub request by URI Source: https://github.com/bblimke/webmock/wiki/Stubbing Stub any request to a specific URI with the default response. ```ruby stub_request(:any, "www.example.com") Net::HTTP.get("www.example.com", "/") # ===> Success ``` -------------------------------- ### Enable WebMock Except Specific Libraries Source: https://context7.com/bblimke/webmock/llms.txt Enables WebMock for all HTTP libraries except for a specified list. This allows certain libraries to bypass WebMock and make real requests. ```ruby WebMock.enable!(except: [:patron, :curb]) # Patron and Curb requests pass through, others intercepted ``` -------------------------------- ### Dynamic Response using Block Source: https://context7.com/bblimke/webmock/llms.txt Generate responses dynamically using a block that receives the request object. This allows for responses that depend on the incoming request details. ```ruby # Dynamic response using block - receives request signature stub_request(:post, "https://api.example.com/echo"). to_return { |request| { status: 200, body: request.body, headers: { 'X-Echoed' => 'true' } } } ``` -------------------------------- ### Simulate Timeouts with to_timeout Source: https://context7.com/bblimke/webmock/llms.txt Simulates request timeouts for testing timeout handling and retry mechanisms. Can be chained with normal responses. ```ruby require 'webmock/rspec' require 'net/http' # Simulate timeout stub_request(:get, "https://api.example.com/slow").to_timeout begin Net::HTTP.get(URI("https://api.example.com/slow")) rescue Net::OpenTimeout, Timeout::Error => e puts "Request timed out" end ``` ```ruby # Timeout then success (for retry logic testing) stub_request(:get, "https://api.example.com/eventually-works"). to_timeout.then. to_timeout.then. to_return(status: 200, body: 'Finally!') ``` ```ruby # Test retry logic attempts = 0 response = nil 3.times do attempts += 1 begin response = Net::HTTP.get_response(URI("https://api.example.com/eventually-works")) break if response.code == "200" rescue Timeout::Error next end end puts "Succeeded after #{attempts} attempts" # => Succeeded after 3 attempts ``` -------------------------------- ### Allow via custom callable Source: https://github.com/bblimke/webmock/wiki/Real-request-handling Use a lambda or object that responds to #call to determine if a URI is allowed. ```ruby blacklist = ['google.com', 'facebook.com', 'apple.com'] allowed_sites = lambda{|uri| blacklist.none?{|site| uri.host.include?(site) } } WebMock.disable_net_connect!(allow: allowed_sites) RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('www.facebook.com', '/') # ===> Failure RestClient.get('apple.com', '/') # ===> Failure ``` -------------------------------- ### WebMock Management Source: https://github.com/bblimke/webmock/blob/master/README.md Utility methods for resetting request history and controlling WebMock state. ```APIDOC ## WebMock.reset! ### Description Resets all current stubs and the history of all executed requests. ## WebMock.reset_executed_requests! ### Description Resets only the counters of the executed requests, keeping the stubs intact. ## WebMock.disable! / WebMock.enable! ### Description Globally enables or disables WebMock, or selectively enables/disables specific HTTP client adapters. ``` -------------------------------- ### WebMock Adapter-Specific Control Source: https://github.com/bblimke/webmock/wiki/Enabling-and-Disabling-WebMock Methods to enable or disable WebMock while excluding specific HTTP client adapters. ```APIDOC ## WebMock.enable!(except: [adapters]) ### Description Enables WebMock for all libraries except those specified in the except array. ## WebMock.disable!(except: [adapters]) ### Description Disables WebMock for all libraries except those specified in the except array. ``` -------------------------------- ### Allow specific host Source: https://github.com/bblimke/webmock/wiki/Real-request-handling Restrict network access to a specific host name. ```ruby WebMock.disable_net_connect!(allow: 'www.example.org') RestClient.get('www.something.com', '/') # ===> Failure RestClient.get('www.example.org', '/') # ===> Allowed RestClient.get('www.example.org:8080', '/') # ===> Allowed ``` -------------------------------- ### Argument Matchers Source: https://github.com/bblimke/webmock/wiki/WebMock-API Matchers for hash arguments in requests. ```APIDOC ## ArgumentMatchers ### Description Matches a hash that includes or excludes specified keys or key/value pairs. ### Methods - hash_including(args) - hash_excluding(args) ``` -------------------------------- ### Rack responses Source: https://github.com/bblimke/webmock/wiki/Stubbing Uses a Rack application to generate the response for a stubbed request. ```ruby class MyRackApp def self.call(env) [200, {}, ["Hello"]] end end stub_request(:get, "www.example.com").to_rack(MyRackApp) RestClient.post('www.example.com') # ===> "Hello" ```