ruby-on-rails 导轨测试:Net::HTTP post -获取外部站点时Rspec中的response.body为空

zc0qhyus  于 2023-02-26  发布在  Ruby
关注(0)|答案(2)|浏览(138)

RSpec行为异常:我从测试中发送了一个发布请求。

context "when webmaster" do
    let(:question) { create(:question) }
    let(:user) { create(:user, :webmaster) }

    describe "creating question from admin form" do
      it "not success" do
        sign_in(user)
        region = "1c5b2444-70a0-4932-980c-b4dc0d3f02b5"
        params = { question: {
          phone: 123,
          region: region_id
        }}

        # Same application
        post :create_from_webmaster_modal, params: params
        expect(response).to have_http_status(:ok)
      end
    end
  end

调用应用程序控制器(同一应用程序)

# This controller in the same application
def create_from_webmaster_modal
  ...
    # Fetch external site
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    response = http.post(uri.path, params.to_json, headers)

    # When called from RSpec, body is empty
    json_response = JSON.parse(response.body) 
  ...
end

...从外部API获取数据。在所有情况下,控制器中的代码从外部API获取数据。
在控制台(rails c)中,在所有环境(生产、开发、测试)中,一切都正常运行,没有错误。
在运行的情况下

RAILS_ENV=test bundle exec rspec

response.body为空,响应为Net::HTTPOK

进入http.post(...)的所有参数均正确。

Rails 5.2
Ruby - 2.5 (yes, it's an old application (( )
Rspec - 3.10

发生什么事了?

5ssjco0h

5ssjco0h1#

这个问题很难回答,因为我们不知道发出请求时发生了什么。您依赖于外部服务在测试套件的任何运行期间可用 *,并且 * 您依赖于它的响应一致。这违反了FIRST principles
您可以尝试通过将binding.irb放入控制器操作中来排除规范故障:

# This controller in the same application
def create_from_webmaster_modal
  ...
    # Fetch external site
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    response = http.post(uri.path, params.to_json, headers)

    binding.irb

    # When called from rspec, body is empty
    json_response = JSON.parse(response.body) 
  ...
end

当你运行测试的时候,它会打开一个REPL,你可以用它来检查ls命令作用域中的所有东西,你应该检查请求中使用的所有变量和方法都是你所期望的。您可以尝试在REPL中重新运行response = http.post(uri.path, params.to_json, headers)命令,以确保它正在建立您所期望的连接。
一个问题是,我们不知道当你运行任何给定的shell命令时,你的shell或应用程序环境是什么样子的。有可能你启动Rails控制台的方式注入了一些环境变量,而你启动RSpec的方式没有注入这些变量。确保你一致地启动它们,并且使用bundle exec,例如:

# Start the console in the test environment to run the request
RAILS_ENV=test bundle exec rails console

# And start rspec in the test environment to run the request
RAILS_ENV=test bundle exec rspec

您还应该检查您的spec_helper.rbrails_helper.rb,以确保您预期的配置没有被覆盖。
但所有这些都是题外话:你不应该在单元测试中测试外部服务的可用性或响应状态。测试 * 你的代码 *,而不是外部服务。对于这样的事情,你应该使用像VCR这样的gem来记录和重放远程请求,这样你的规范总是可重复的、一致的和快速的。或者,你可以只使用mock it

njthzxwz

njthzxwz2#

免责声明:我没有足够的声誉来评论,这篇文章最好是一个评论
我在一个全新的rails应用程序上进行了测试,添加了HTTParty并请求了与您在env中相同的url:正文不为空

我觉得问题不在httpparty
你的Railsenv中是否有任何初始化器或库可能只在测试环境中禁用netconnect?比如webmock之类的东西?下面是webmock的用法以及它如何返回空的body
也许在"spec_helper. rb"级别,您只能看到测试套件中的问题?


这可以解释任何URL获取都返回http成功代码和空正文
您是否可以尝试在HTTParty.get中输入无效的URL?
例如HTTParty.get('https://invalidexample.com/').body如果仍然有200 OK和空主体,则在某处有一个lib,它只在TEST ENV上篡改外部请求
(as指出在其他答案这应该是最好的方式来测试您的代码无论如何,没有真正的联系)

相关问题