carrierwave_direct icon indicating copy to clipboard operation
carrierwave_direct copied to clipboard

How to Properly Configure Test Environment?

Open sshaw opened this issue 3 years ago • 2 comments

This is what I have:

CarrierWave.configure do |config|
  config.storage = :file
  config.enable_processing = false
  config.asset_host = ActionController::Base.asset_host
end

# Still must be set even though we've set it above in configure
DirectUploader.storage = :file

Seemed to be working fine, doing things like:

# io is from File.open
model.create_attachment!(file: io)

Until I added code like this:

model.remote_whatever_key = "https://example.com/foo/bar"

Then I get:

  WebMock::NetConnectNotAllowedError:
       Real HTTP connections are disabled. Unregistered request: GET https://example.com/foo/bar

Looking at the docs I see this but adding that results in the same WebMock error.

When I add it and remove the file settings above calls to:

model.create_attachment!(file: io)

Fail with:

     Excon::Error::NotFound:
       Expected(200) <=> Actual(404 Not Found)

How can I configure this so that both styles of uploading are stored locally and do not result in network requests?

sshaw avatar Aug 05 '21 16:08 sshaw

Running into this issue with the Excon::Error::NotFound: Expected(200) <=> Actual(404 Not Found) error when creating objects for my tests using the standard Fog.mock! setup when upgrading a long-running Rails app from Ruby/Rails 2.6/6.0 to 3.0/6.1, and carrierwave_direct from 0.0.15 to current 3.0.0.

Running the CarrierWave, CarrierWaveDirect, and Fog gems locally, I have isolated the problem to CarrierWaveDirect::Uploader lines 20-24:

      fog_credentials.keys.each do |key|
        define_method(key) do
          fog_credentials[key]
        end
      end

It appears that CarrierWaveDirect's referencing fog_credentials in the Uploader's included block results in cacheing a Fog connection that is invalid for testing purposes. Simply referencing this fog_credentials hash as part of the included block triggers the error, and removing this block allows the test objects to be created without error.

The CarrierWave gem contains an eager_load initializer that creates and caches a new Fog connection during initialization, keyed off the credentials:

        def eager_load
          # see #1198. This will hopefully no longer be necessary in future release of fog
          fog_credentials = CarrierWave::Uploader::Base.fog_credentials
          if fog_credentials.present?
            CarrierWave::Storage::Fog.connection_cache[fog_credentials] ||= ::Fog::Storage.new(fog_credentials)
          end
        end

In the testing environment, it seems like the testing configuration is being overridden with the result of this eager_load method Fog::Storage.new(fog_credentials).

This eager_load method is ~3 years old (relatively new, at least in terms of our use of the gem).

lawso017 avatar Jan 28 '23 14:01 lawso017

Discovered a workaround after watching the load sequence; it looked like Fog was initializing with credentials first out of the .env environment variables, and then being overridden with the credentials in the spec initializer. For some reason, the aws_access_key_id being set to the non-test value initially was the issue. The "fix" at the moment is hacking config/initializers/carrierwave.rb so that the aws_access_key_id is given the test value in the test environment:

CarrierWave.configure do |config|
  config.storage = :fog
  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: Rails.env.test? ? 'aws_access_key_id' : ENV['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
  }
...

lawso017 avatar Jan 28 '23 15:01 lawso017