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
发生什么事了?
2条答案
按热度按时间5ssjco0h1#
这个问题很难回答,因为我们不知道发出请求时发生了什么。您依赖于外部服务在测试套件的任何运行期间可用 *,并且 * 您依赖于它的响应一致。这违反了FIRST principles。
您可以尝试通过将
binding.irb
放入控制器操作中来排除规范故障:当你运行测试的时候,它会打开一个REPL,你可以用它来检查
ls
命令作用域中的所有东西,你应该检查请求中使用的所有变量和方法都是你所期望的。您可以尝试在REPL中重新运行response = http.post(uri.path, params.to_json, headers)
命令,以确保它正在建立您所期望的连接。一个问题是,我们不知道当你运行任何给定的shell命令时,你的shell或应用程序环境是什么样子的。有可能你启动Rails控制台的方式注入了一些环境变量,而你启动RSpec的方式没有注入这些变量。确保你一致地启动它们,并且使用
bundle exec
,例如:您还应该检查您的
spec_helper.rb
和rails_helper.rb
,以确保您预期的配置没有被覆盖。但所有这些都是题外话:你不应该在单元测试中测试外部服务的可用性或响应状态。测试 * 你的代码 *,而不是外部服务。对于这样的事情,你应该使用像VCR这样的gem来记录和重放远程请求,这样你的规范总是可重复的、一致的和快速的。或者,你可以只使用mock it。
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指出在其他答案这应该是最好的方式来测试您的代码无论如何,没有真正的联系)