webmock icon indicating copy to clipboard operation
webmock copied to clipboard

can't modify frozen String: ""

Open utkarsh2102 opened this issue 5 years ago • 3 comments

Hi,

There are following test failures:

Failures:

  1) HTTP.rb with WebMock allows a response with multiple values for the same header to be recorded and played back exactly as-is
     Failure/Error: webmock_response.body    = body.to_s
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "complex cross-concern behaviors" called from ./spec/acceptance/webmock_shared.rb:39
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./lib/webmock/http_lib_adapters/http_rb/response.rb:7:in `to_webmock'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:52:in `perform'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:10:in `exec'
     # ./lib/webmock/http_lib_adapters/http_rb/client.rb:7:in `perform'
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:14:in `http_request'
     # ./spec/acceptance/shared/complex_cross_concern_behaviors.rb:7:in `block (2 levels) in <top (required)>'

  2) HTTP.rb with WebMock when webmock is disabled should not register executed requests
     Failure/Error: body: response.body.to_s,
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:9
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:44:in `block (2 levels) in <top (required)>'

  3) HTTP.rb with WebMock when webmock is disabled should not block unstubbed requests
     Failure/Error:
       expect {
         http_request(:get, webmock_server_url)
       }.not_to raise_error
     
       expected no Exception, got #<FrozenError: can't modify frozen String: ""> with backtrace:
         # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
         # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:50:in `block (3 levels) in <top (required)>'
         # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:49:in `block (2 levels) in <top (required)>'
     Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:9
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:49:in `block (2 levels) in <top (required)>'

  4) HTTP.rb with WebMock when webmock is disabled should return real response even if there are stubs
     Failure/Error: body: response.body.to_s,
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:9
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:56:in `block (2 levels) in <top (required)>'

  5) HTTP.rb with WebMock when webmock is disabled should not invoke any callbacks
     Failure/Error: body: response.body.to_s,
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:9
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:64:in `block (2 levels) in <top (required)>'

  6) HTTP.rb with WebMock when webmock is enabled again should register executed requests
     Failure/Error: webmock_response.body    = body.to_s
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "enabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:17
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./lib/webmock/http_lib_adapters/http_rb/response.rb:7:in `to_webmock'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:52:in `perform'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:10:in `exec'
     # ./lib/webmock/http_lib_adapters/http_rb/client.rb:7:in `perform'
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:14:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:72:in `block (2 levels) in <top (required)>'

  7) HTTP.rb with WebMock when webmock is enabled again should invoke callbacks
     Failure/Error: webmock_response.body    = body.to_s
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "enabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:17
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./lib/webmock/http_lib_adapters/http_rb/response.rb:7:in `to_webmock'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:52:in `perform'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:10:in `exec'
     # ./lib/webmock/http_lib_adapters/http_rb/client.rb:7:in `perform'
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:14:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:92:in `block (2 levels) in <top (required)>'

  8) HTTP.rb with WebMock when webmock is disabled except this lib should register executed requests
     Failure/Error: webmock_response.body    = body.to_s
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "enabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:27
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./lib/webmock/http_lib_adapters/http_rb/response.rb:7:in `to_webmock'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:52:in `perform'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:10:in `exec'
     # ./lib/webmock/http_lib_adapters/http_rb/client.rb:7:in `perform'
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:14:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:72:in `block (2 levels) in <top (required)>'

  9) HTTP.rb with WebMock when webmock is disabled except this lib should invoke callbacks
     Failure/Error: webmock_response.body    = body.to_s
     
     FrozenError:
       can't modify frozen String: ""
     Shared Example Group: "enabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:27
     Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
     Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
     # ./lib/webmock/http_lib_adapters/http_rb/response.rb:7:in `to_webmock'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:52:in `perform'
     # ./lib/webmock/http_lib_adapters/http_rb/webmock.rb:10:in `exec'
     # ./lib/webmock/http_lib_adapters/http_rb/client.rb:7:in `perform'
     # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:14:in `http_request'
     # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:92:in `block (2 levels) in <top (required)>'

  10) HTTP.rb with WebMock when webmock is enabled except this lib should not register executed requests
      Failure/Error: body: response.body.to_s,
      
      FrozenError:
        can't modify frozen String: ""
      Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:38
      Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
      Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
      # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
      # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:44:in `block (2 levels) in <top (required)>'

  11) HTTP.rb with WebMock when webmock is enabled except this lib should not block unstubbed requests
      Failure/Error:
        expect {
          http_request(:get, webmock_server_url)
        }.not_to raise_error
      
        expected no Exception, got #<FrozenError: can't modify frozen String: ""> with backtrace:
          # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
          # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:50:in `block (3 levels) in <top (required)>'
          # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:49:in `block (2 levels) in <top (required)>'
      Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:38
      Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
      Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
      # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:49:in `block (2 levels) in <top (required)>'

  12) HTTP.rb with WebMock when webmock is enabled except this lib should return real response even if there are stubs
      Failure/Error: body: response.body.to_s,
      
      FrozenError:
        can't modify frozen String: ""
      Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:38
      Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
      Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
      # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
      # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:56:in `block (2 levels) in <top (required)>'

  13) HTTP.rb with WebMock when webmock is enabled except this lib should not invoke any callbacks
      Failure/Error: body: response.body.to_s,
      
      FrozenError:
        can't modify frozen String: ""
      Shared Example Group: "disabled WebMock" called from ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:38
      Shared Example Group: "enabled and disabled webmock" called from ./spec/acceptance/webmock_shared.rb:37
      Shared Example Group: "with WebMock" called from ./spec/acceptance/http_rb/http_rb_spec.rb:10
      # ./spec/acceptance/http_rb/http_rb_spec_helper.rb:17:in `http_request'
      # ./spec/acceptance/shared/enabling_and_disabling_webmock.rb:64:in `block (2 levels) in <top (required)>'

Finished in 10.53 seconds (files took 2.18 seconds to load)
4028 examples, 13 failures

Failed examples:

rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:14]' # HTTP.rb with WebMock allows a response with multiple values for the same header to be recorded and played back exactly as-is
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:10:1]' # HTTP.rb with WebMock when webmock is disabled should not register executed requests
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:10:2]' # HTTP.rb with WebMock when webmock is disabled should not block unstubbed requests
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:10:3]' # HTTP.rb with WebMock when webmock is disabled should return real response even if there are stubs
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:10:4]' # HTTP.rb with WebMock when webmock is disabled should not invoke any callbacks
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:11:1]' # HTTP.rb with WebMock when webmock is enabled again should register executed requests
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:11:4]' # HTTP.rb with WebMock when webmock is enabled again should invoke callbacks
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:12:1]' # HTTP.rb with WebMock when webmock is disabled except this lib should register executed requests
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:12:4]' # HTTP.rb with WebMock when webmock is disabled except this lib should invoke callbacks
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:13:1]' # HTTP.rb with WebMock when webmock is enabled except this lib should not register executed requests
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:13:2]' # HTTP.rb with WebMock when webmock is enabled except this lib should not block unstubbed requests
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:13:3]' # HTTP.rb with WebMock when webmock is enabled except this lib should return real response even if there are stubs
rspec './spec/acceptance/http_rb/http_rb_spec.rb[1:1:13:4]' # HTTP.rb with WebMock when webmock is enabled except this lib should not invoke any callbacks

Now, I am confused whether it is related to webmock or related to http?

utkarsh2102 avatar Mar 29 '20 21:03 utkarsh2102

@utkarsh2102 how can it be reproducted? what ruby version that is?

bblimke avatar Mar 30 '20 16:03 bblimke

Let me guess. It started with ruby 2.7? In my library (a wrapper on Net::HTTP) I do:

response.body.tap{ |r| r.instance_variable_set :@last_response, response }

and once I stub the request as

.to_return status: 200

it falls with

in `instance_variable_set': can't modify frozen String: "" (FrozenError)

Haven't debugged it thoroughly but it feels like the stub returns a frozen string and it's not what real Net::HTTP does.

UPD: kludge fix: add , body: "" to the stubbing

Nakilon avatar Oct 06 '23 02:10 Nakilon

Thank you for reporting, @utkarsh2102 and @Nakilon. I've addressed the issue by updating the response body to an empty, unfrozen string. This change will be included in the upcoming release.

bblimke avatar Feb 05 '24 18:02 bblimke