2

以下代码在带有 RSpec 3.5 和Shrine gem的 Rails 4.2 应用程序的模型规范中测试图像验证以进行文件上传。

我的问题是:

  • 您能想出一种改进以下测试的方法或更好的方法来测试这些验证吗?
  • 如何提高文件大小验证测试的速度?如果可能的话,我想对其进行测试,而无需实际上传 >10mb 的文件。

文件上传设置的其他方面在控制器和功能规范中进行了测试,这与这个问题无关。

RSpec.describe ShareImage, :type => :model do
  describe "#image", :focus do
    let(:image_file) do
      # Could not get fixture_file_upload to work, but that's irrelevant
      Rack::Test::UploadedFile.new(File.join(
        ActionController::TestCase.fixture_path, 'files', filename))
    end
    let(:share_image) { FactoryGirl.build(:share_image, image: image_file) }
    before(:each) { share_image.valid? }

    context "with a valid image file" do
      let(:filename) { 'image-valid.jpg' }
      it "attaches the image to this record" do
        expect(share_image.image.metadata["filename"]).to eq filename
      end
    end

    context "with JPG extension and 'text/plain' media type" do
      let(:filename) { 'image-with-text-media-type.jpg' }
      it "is invalid" do
        expect(share_image.errors[:image].to_s).to include("invalid file type")
      end
    end

    # TODO: Refactor the following test (it takes ~50 seconds to run)
    context "with a >10mb image file" do
      let(:filename) { 'image-11mb.jpg' }
      it "is invalid" do
        expect(share_image.errors[:image].to_s).to include("too large")
      end
    end
  end
end
4

2 回答 2

4

我建议您分别测试元数据提取和验证。您需要使用真实的 IO 测试元数据提取,但对于验证测试,您可以分配一个缓存文件,其中包含不需要实际存在的所需元数据。

RSpec.describe ImageUploader do
  def uploaded_file(metadata = {})
    Shrine.uploaded_file(
      "id"       => "123",
      "storage"  => "cache",
      "metadata" => {"mime_type" => "image/jpeg", "size" => 100}.merge(metadata)
    )
  end

  let(:share_image) do
    FactoryGirl.build(:share_image, image: uploaded_file(metadata).to_json)
  end

  let(:metadata) { Hash.new }

  describe "validations" do
    before(:each) { share_image.valid? }

    context "when image is correct" do
      it "passes" do
        expect(share_image.errors).to be_empty
      end
    end

    context "when extension is correct but MIME types isn't" do
      let(:metadata) { Hash["filename" => "image.jpg", mime_type => "text/plain"] }

      it "fails" do
        expect(share_image.errors[:image].to_s).to include("isn't of allowed type")
      end
    end

    context "when file is larger than 10MB" do
      let(:metadata) { Hash["size" => 11 * 1024 * 1024] }

      it "fails" do
        expect(share_image.errors[:image].to_s).to include("too large")
      end
    end
  end
end
于 2017-07-01T23:15:29.040 回答
1

不是通过 路由上传,而是Rack::Test::UploadedFile直接使用夹具或工厂或直接在测试中创建附件元数据记录。最终结果应该是您拥有引用您的文件的附件元数据(这是在您上传文件时构建的),而无需通过上传代码运行它。我不确定使用 Shrine 执行此操作的具体细节,但这种技术适用于 Paperclip 之类的库。在 Shrine 中,这似乎意味着Shrine::UploadedFile直接构建一条引用您的文件的记录。

于 2017-06-28T21:24:44.900 回答