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

Webmock matchers and forked processes #1062

Open
kwstannard opened this issue Jul 15, 2024 · 2 comments
Open

Webmock matchers and forked processes #1062

kwstannard opened this issue Jul 15, 2024 · 2 comments

Comments

@kwstannard
Copy link

I think this is maybe a feature request. WebMock matchers do not work with forking. This makes sense logically given that a web request will change the stub object and trigger copy-on-write. It would be great if there was a way to have the copied stub in the fork send back the recorded requests to the main process stub though.

Ruby 3.3.3
WebMock 3.23.1

require 'webmock'
require 'webmock/rspec'

def fork_code
  3.times {
    fork do
      Net::HTTP.get(URI.parse('http://localhost'))
    end
  }
  Process.waitall
end

def thread_code
  3.times {
    Thread.new do
      Net::HTTP.get(URI.parse('http://localhost'))
    end
  }
  Process.waitall
end

# test
WebMock.enable!
WebMock.disable_net_connect!
stub = WebMock.stub_request(:get, 'localhost').and_return(body: ->(_) { printf 'Called! '; ''} )

fork_code

matcher = WebMock::RequestPatternMatcher.new.times(3)
puts "Does the main process count forked requests? #{matcher.matches?(stub)}"
puts
puts matcher.failure_message

thread_code

matcher = WebMock::RequestPatternMatcher.new.times(3)
puts "Does the main process count threaded requests? #{matcher.matches?(stub)}"
puts
puts matcher.failure_message
~ $ ruby /tmp/fork_spec.rb
Called! Called! Called! Does the main process count forked requests? false

The request GET http://localhost/ was expected to execute 3 times but it executed 0 times

The following requests were made:

No requests were made.
============================================================
Called! Called! Called! Does the main process count threaded requests? true

The request GET http://localhost/ was expected to execute 3 times but it executed 3 times

The following requests were made:

GET http://localhost/ with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Host'=>'localhost', 'User-Agent'=>'Ruby'} was made 3 times

============================================================
@bblimke
Copy link
Owner

bblimke commented Jul 15, 2024

@kwstannard I understand the issue and what you're trying to achieve. However, this isn't something WebMock is designed to handle. WebMock uses global registries in the current process's memory and doesn't differentiate between main and subprocesses. The behaviour you're seeing is correct given how forking works.

Here are some ideas on how you could solve that:

  1. Using Inter-Process Communication (IPC) to send WebMock registry data from subprocesses to the main process.
  2. Implementing a shared storage solution (like a database or file) that all processes can access and overwrite WebMock registries to use that storage instead of the default memory storage.
  3. Creating some kind of wrapper around WebMock that's aware of forking, though I'm not sure how this would work.

@kwstannard
Copy link
Author

Thanks bblimke.

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

No branches or pull requests

2 participants