carrierwaveuploader / carrierwave-aws

AWS-SDK storage adapter for CarrierWave
MIT License
409 stars 107 forks source link

Could not read file contents in test environment #172

Closed khataev closed 1 year ago

khataev commented 2 years ago

This is my configuration:

CarrierWave.configure do |config|
    config.storage    = :aws
    config.aws_bucket = Settings.aws.s3.bucket_name # for AWS-side bucket access permissions config, see section below
    config.aws_acl    = "private"

    # The maximum period for authenticated_urls is only 7 days.
    config.aws_authenticated_url_expiration = 60 * 60 * 24 * 7

    # Set custom options such as cache control to leverage browser caching.
    # You can use either a static Hash or a Proc.
    config.aws_attributes = lambda do
      {
        expires:       1.week.from_now.httpdate,
        cache_control: "max-age=604800"
      }
    end

    config.aws_credentials = {
      access_key_id:     Settings.aws.s3.access_key_id,
      secret_access_key: Settings.aws.s3.secret_access_key,
      region:            Settings.aws.s3.region, # Required
      stub_responses:    Rails.env.test? # Optional, avoid hitting S3 actual during tests
    }
  end

model:

mount_uploader :declaration_xml_file, Uploaders::Declaration::Xml

uploader:

module Uploaders
  module Declaration
    class Xml < CarrierWave::Uploader::Base
      storage :aws

      def store_dir
        "declaration/xml/user_#{model.order.user_id}/order_#{model.order_id}/calculation_#{model.id}"
      end

      def extension_allowlist
        %w[xml]
      end
    end
  end
end

this is how I setup file and factory in a test:

  let(:declaration_file) do
    Rack::Test::UploadedFile.new(
      Rails.root.join("spec/fixtures/ndfl3/reference/trades/abmd.xml"),
      "application/xml"
    )
  end
  let(:calculation) do
    create :calculation,
           order:                order,
           tax_base_file:        tax_base_file,
           tax_base_done:        true,
           declaration_xml_file: declaration_file,
           declaration_xml_done: true,
           paid:                 false,
           payment_id:           0
  end

when I try to read file's contents it returns empty string:

0> calculation.declaration_xml_file.read
=> ""

How to fix it?

On other project that used pure fog-carrierwave we did something like here , in test environment we do not use AWS, we use file storage.

if Rails.env.test?
  CarrierWave.configure do |config|
    config.storage           = :file
    config.enable_processing = false
  end
else
 # ... main config
end

With carrierwave-aws it does not work, I get an error, that bucket name is not set. So my question how to set test env config properly, ideally to use file storage and to be able to download/get file and its contents. Thanks!

khataev commented 2 years ago

This is my workaround

class Uploaders::Base < CarrierWave::Uploader::Base
  STORAGE = (Rails.env.test? ? :file : :aws).freeze

  storage STORAGE
end
mshibuya commented 1 year ago
      stub_responses:    Rails.env.test? # Optional, avoid hitting S3 actual during tests

Obviously, this disables the API interaction and requests will no longer reach S3. Set it to false when you don't need. https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/stubbing.html