为什么我会遇到 string/hash 比较失败?

Why am I getting a string/hash comparison failure?

我编写了一个函数来发出 HTTP GET 请求(截断和简化)。

# get_request.rb
require "http"

def get_request
  HTTP.get("<https://github.com>")
end

我已经为请求编写了测试。

require "request"

RSpec.describe "#get_request" do
  it "makes a successful GET request" do
    # GIVEN
    http_response = double("http", body: "Hello world!")

    # WHEN
    response = get_request

    # THEN
    expect(HTTP).to receive(:get).with("<https://github.com>").and_return(http_response)
    expect(response.body).to eq("Hello world!")
  end
end

但是,测试因比较失败而失败。

$ bundle exec rspec
F

Failures:

  1) #get_request makes a successful GET request
     Failure/Error: expect(response.body).to eq("Hello world!")

       expected: "Hello world!"
            got: #<HTTP::Response::Body:3fe63e519550 @streaming=false>

       (compared using ==)

       Diff:
       @@ -1,2 +1,2 @@
       -"Hello world!"
       +#<HTTP::Response::Body:3fe63e519550 @streaming=false>

     # ./spec/request_spec.rb:13:in `block (2 levels) in <top (required)>'

Finished in 0.32713 seconds (files took 0.25261 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/request_spec.rb:4 # #get_request makes a successful GET request

为什么 response.body 等于 <HTTP::Response::Body:3fe63e519550 @streaming=false> 散列而不是我预期的 "Hello world!" 字符串?我如何才能通过测试?

测试替身需要在调用函数之前就位。¹要让测试通过,请将第一个期望移到 get_request 方法之上。

例如:

require "request"

RSpec.describe "#get_request" do
  it "makes a successful GET request" do
    # GIVEN
    http_response = double("http", body: "Hello world!")
    expect(HTTP).to receive(:get).with("<https://github.com>").and_return(http_response)

    # WHEN
    response = get_request

    # THEN
    expect(response.body).to eq("Hello world!")
  end
end

¹感谢 Jeremy Weathers 帮助回答问题的 "why" 部分。

如果你想在测试的底部有异常,你必须使用间谍模式。 https://relishapp.com/rspec/rspec-mocks/docs/basics/spies

RSpec.describe "#get_request" do
  it "performs the request successfully" do
        http_response = double("http", body: "Hello world!")
        allow(HTTP).to receive(:get).and_return(http_response)

        response = get_request

        expect(HTTP).to have_received(:get).with("https://www.github.com")
        expect(response).to eq(http_response)
  end
end