philiprehberger-http_mock
Lightweight HTTP request stubbing for tests
Requirements
- Ruby >= 3.1
Installation
Add to your Gemfile:
gem "philiprehberger-http_mock"Or install directly:
gem install philiprehberger-http_mockUsage
require "philiprehberger/http_mock"
Philiprehberger::HttpMock.stub(:get, "https://api.example.com/users")
.to_return(status: 200, body: '{"users":[]}')
response = Philiprehberger::HttpMock.request(:get, "https://api.example.com/users")
response.status # => 200
response.body # => '{"users":[]}'POST with Body Matching
Philiprehberger::HttpMock.stub(:post, "https://api.example.com/users")
.with(body: '{"name":"Alice"}')
.to_return(status: 201, body: '{"id":1}')Header Matching
Philiprehberger::HttpMock.stub(:get, "https://api.example.com/data")
.with(headers: { "Authorization" => "Bearer token123" })
.to_return(status: 200, body: "secret")Response Sequences
Philiprehberger::HttpMock.stub(:get, "https://api.example.com/flaky")
.to_return_in_sequence([
{ status: 503, body: "unavailable" },
{ status: 200, body: "ok" }
])
Philiprehberger::HttpMock.request(:get, "https://api.example.com/flaky").status # => 503
Philiprehberger::HttpMock.request(:get, "https://api.example.com/flaky").status # => 200
Philiprehberger::HttpMock.request(:get, "https://api.example.com/flaky").status # => 200 (repeats last)Callback Responses
Philiprehberger::HttpMock.stub(:post, "https://api.example.com/echo")
.to_return { |request| { status: 200, body: request.body.upcase } }
response = Philiprehberger::HttpMock.request(:post, "https://api.example.com/echo", body: "hello")
response.body # => "HELLO"Stub Verification
stub = Philiprehberger::HttpMock.stub(:get, "https://api.example.com/data")
.to_return(status: 200)
Philiprehberger::HttpMock.request(:get, "https://api.example.com/data")
stub.called? # => true
stub.call_count # => 1
Philiprehberger::HttpMock.verify! # raises UnmatchedStubError if any stub was never calledRequest Recording
Philiprehberger::HttpMock.stub(:get, "https://api.example.com/data").to_return(status: 200)
Philiprehberger::HttpMock.request(:get, "https://api.example.com/data")
requests = Philiprehberger::HttpMock.requests
requests.length # => 1
requests.first.url # => "https://api.example.com/data"Scoped Isolation
Philiprehberger::HttpMock.scope do
Philiprehberger::HttpMock.stub(:get, "https://api.example.com/temp")
.to_return(status: 200)
# Stubs are automatically cleaned up after the block
endAPI
HttpMock
| Method | Description |
|---|---|
.stub(method, url) |
Create a request stub, returns a chainable stub definition |
.request(method, url, body:, headers:) |
Simulate a request against registered stubs |
.requests |
Get all recorded requests |
.verify! |
Raise UnmatchedStubError if any stub was never called |
.reset! |
Clear all stubs and recorded requests |
.scope { ... } |
Execute a block with isolated stubs |
StubDefinition
| Method | Description |
|---|---|
#with(body:, headers:) |
Add matching constraints for body and/or headers |
#to_return(status:, body:, headers:) |
Set the response to return |
#to_return { |request| ... } |
Set a dynamic response callback |
#to_return_in_sequence(responses) |
Set an ordered sequence of responses |
#call_count |
Number of times this stub has been matched |
#called? |
Whether this stub has been matched at least once |
Development
bundle install
bundle exec rspec
bundle exec rubocopSupport
If you find this project useful: