从RSpec发送真正的JSON帖子请求

时间:2017-09-20 08:52:00

标签: ruby-on-rails rspec

我希望能够为端点响应测试远程3d party API,这就是为什么我想编写一堆本地rspec测试并定期启动它们,以查看这些端点是否按预期工作没有重大变化。由于我的应用程序高度依赖于这种不断变化的API,我别无选择,只能自动化我的测试。

目前我采用了常规的rspec API测试代码:

require "rails_helper"

RSpec.describe "Remote request", type: :request do
  describe ".send request" do
    it ".posts valid data" do
      post "http://123.45.67.89/api/endpoint",
        params: {
                  "job_request_id": 123456,
                  "data": "12345",
                  "app_secret": "12345",
                  "options": {
                     ...
                  }
                }

      expect(JSON.parse response.body).to include("message" => "success")
      expect(response).to have_http_status(200)
    end
  end
end

此代码的问题在于Rspec正在点击/api/endpoint网址,而不是完整的http://123.45.67.89/api/endpoint网址。我该如何改变这种行为?

1 个答案:

答案 0 :(得分:1)

RSpec的请求规范用于测试您自己的应用程序 - 通过发送真实的HTTP请求。它们不用于执行远程HTTP请求(即使可能使用配置来请求其他主机而不是localhost)。

除其他事项外,请求规范将针对每个示例点击API - 这将为您提供速率限制和限制的问题。

虽然您可以尝试在请求规范中使用Net::HTTPHttpartyTyphoeus等HTTP库,但您真正应该做的是重新考虑您的方法。隔离应用程序与外部协作者之间的交互是个好主意。

这样做的一种方法是创建使用远程API的客户端类:

class ExampleAPIClient
  include HTTParty
  base_url 'example.com'
  format :json

  def get_some_data
    self.class.get('/foo')
  end
end

然后,您可以通过像普通的旧Ruby对象一样测试客户端来测试远程端点:

require 'spec_helper'
RSpec.describe ExampleAPIClient do
  let(:client) { described_class.new }

  describe "#get_some_data" do
    let(:response) { client.get_some_data }
    it "should be successful" do
      expect(response.success?).to be_truthy
    end 
  end
end

这将带来额外的好处,即限制应用程序中的更改,因为如果远程api发生更改,只有单个组件(客户端)会失败。

使用客户端的其他组件可以通过存根客户端轻松地存根远程交互。