webmock icon indicating copy to clipboard operation
webmock copied to clipboard

WebMock breaks Async::WebSocket

Open zhulik opened this issue 4 years ago • 4 comments

Hello,

I'm currently working on a project that uses Async::WebSocket to interact with a database running locally and Async::HTTP to call some 3rd party services.

I wanted to use WebMock to prevent the test suite from making any network requests, but allow it to interact with the database.

An attempt to open a websocket connection with enabled WebMock blocking leads to an error:

     3.2) Failure/Error: Async::WebSocket::Client.connect(endpoint)
          
          NoMethodError:
            undefined method `acquire' for nil:NilClass
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/async-websocket-0.19.0/lib/async/websocket/client.rb:93:in `connect'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/async-websocket-0.19.0/lib/async/websocket/client.rb:53:in `connect'
          # ./spec/demo_spec.rb:74:in `block (4 levels) in <top (required)>'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:262:in `instance_exec'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:262:in `block in run'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:508:in `block in with_around_and_singleton_context_hooks'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:465:in `block in with_around_example_hooks'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:486:in `block in run'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:626:in `block in run_around_example_hooks_for'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:350:in `call'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/async-rspec-1.16.1/lib/async/rspec/reactor.rb:93:in `block (4 levels) in <module:RSpec>'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/async-rspec-1.16.1/lib/async/rspec/reactor.rb:57:in `block in run_in_reactor'
          # /home/zhulik/.asdf/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/async-1.30.1/lib/async/task.rb:260:in `block in make_fiber'

It is expected that WebMock should not care about websockets, but at least it should not break them if the host is in the allowlist.

I prepared a minimal demo app that reproduces this error: https://github.com/zhulik/async-http-webmock-bug-demo

Thanks you!

zhulik avatar Aug 30 '21 21:08 zhulik

@ioquatix would you mind having a look? Maybe the problem is somewhere in the Async stack

zhulik avatar Aug 30 '21 21:08 zhulik

Sure.

ioquatix avatar Aug 30 '21 22:08 ioquatix

Also running into this issue and would love to help working towards a fix.

I'm not too familiar with Async so probably wouldn't be much help directly fixing the bug, but if a repro script would be useful please let me know.

odlp avatar May 09 '24 09:05 odlp

Mocking async-http can be complicated due to the nature of the internal implementation and the full support for streaming, web sockets, proxies, etc.

The plan is to introduce a mechanism for redirecting / mocking requests directly in Async::HTTP: https://github.com/socketry/async-http/pull/41

It will require some more work, but I think the plan is to provide a hook such that web mock can say "I'll hijack requests with this middleware" and handle them using a standard interface.

ioquatix avatar May 09 '24 10:05 ioquatix