如何在RSpec中正确模拟对象?

时间:2018-05-15 17:51:39

标签: ruby rspec

我有一个简单的类,它为存储在S3上的文件生成一个下载URL,我需要编写一个单元测试来测试这个类。到目前为止,我没有运气。

class S3DownloadUrlGenerator
  def initialize(filename)
    @filename = filename
  end

  def presigned_url
    signer = Aws::S3::Presigner.new(client: s3)
    signer.presigned_url(
      :get_object,
      bucket: "my-bucket",
      key: filename,
      response_content_disposition: "attachment",
    )
  end

  private

  def s3
    @s3 ||= Aws::S3::Client.new(
      region: "my-region,
      http_open_timeout: 5,
      http_read_timeout: 25,
    )
  end

  attr_reader :filename
end

我想测试在S3DownloadUrlGenerator的实例上调用#presigned_url是否返回一个URL。 这是我的考验:

describe S3DownloadUrlGenerator do
  before do
    allow(Aws::S3::Client).to receive(:new) { s3_client }
  end
  let(:s3_client) { spy("s3 client") }
  let(:presigner) { spy("s3 presigner") }

  it "generates download URL for a file" do
    expect(Aws::S3::Presigner).to receive(:new).with(client: s3_client).and_return(presigner)
    expect(presigner).to receive(:presigned_url).with(
      :get_object,
      bucket: "my-test-bucket",
      key: "test_file.txt",
      response_content_disposition: "attachment",
    ).and_return("https://www.example.com")
    expect(described_class.new("Test_file.txt").presigned_url).to eq("https://www.example.com")
  end
end

但是我收到了错误:

Failure/Error: expect(described_class.new("Test_file.txt").presigned_url).to eq("https://www.example.com")

       expected: "https://www.example.com"
            got: #<Double "s3 presigner">

       (compared using ==)

我对此有点新意,我想学习如何正确测试这些案例。非常感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

存储桶和关键参数在实际调用和模拟方面有所不同。 使用下面的代码:

describe S3DownloadUrlGenerator do
  before do
    allow(Aws::S3::Client).to receive(:new) { s3_client }
  end
  let(:s3_client) { spy("s3 client") }
  let(:presigner) { spy("s3 presigner") }
  it "generates download URL for a file" do
    expect(Aws::S3::Presigner).to receive(:new).with(client: s3_client).and_return(presigner)
    expect(presigner).to receive(:presigned_url).with(
      :get_object,
      bucket: "my-bucket",
      key: "Test_file.txt",
      response_content_disposition: "attachment",
    ).and_return("https://www.example.com")
    expect(described_class.new("Test_file.txt").presigned_url).to eq("https://www.example.com")
  end
end