有没有办法在 RSpec 控制器测试中测试模板是否具有属性?

Is there a way to test whether a template has properties in an RSpec controller test?

所以我正在处理我的第一个 Rails 项目,并且正在努力设置一些自动化测试。现在,我有一个带有 select 标签的表单模板,它根据模拟的 API 响应动态获取信息。截至目前,我的模板已成功呈现,但我希望能够访问该 select 标记并查看其子 options 是否与我的模拟 API 响应匹配。未能在文档中找到关于此特定用例的大量信息,希望这里的某个人能够为我指明正确的方向。这基本上是我到目前为止所拥有的:

RSpec.describe MyController, type: :controller, do
  describe "GET my_thing/index" do
    it "renders the index template" do
      stub_request(:get, "https://outsideapi.net/endpoint").
        to_return(status: 200,
                  body: {
                    "values" => [
                      { "name": "foo", "id": "10000" },
                      { "name": "bar", "id": "10001" },
                      { "name": "baz", "id": "10002" },
                     ],
                  }.to_json,
                  headers: {})

      get :index, params: { request_identifier: generate_request_identifier() }
      expect(response).to have_http_status(:success)
      expect(response).to render_template(:index)
      # Some code that will hopefully get elements off the template
    end
  end

根据 Rspec docs 控制器测试:

by default, views are not rendered. See views are stubbed by default and render_views for details.

首先,您需要通过在测试套件中添加 render_views 指令来指示 Rspec 呈现控制器视图,如 mentioned here:

require "rails_helper"

RSpec.describe WidgetsController, :type => :controller do
  render_views # <-- This

  describe "GET index" do
    it "has a widgets related heading" do
      get :index
      expect(response.body).to match /<h1>.*widgets/im
    end
  end
end

最后,您将能够使用类似这样的东西将 JSON 数组与呈现的 HTML 相匹配(代码未经测试,但它应该有望驱动要点):


RSpec.describe MyController, type: :controller, do
  describe "GET my_thing/index" do
    it "renders the index template" do
      # Can also be added below the `describe` call if view rendering is needed elsewhere.
      render_views
      select_values = [
                      { "name": "foo", "id": "10000" },
                      { "name": "bar", "id": "10001" },
                      { "name": "baz", "id": "10002" },
                     ]
      stub_request(:get, "https://outsideapi.net/endpoint").
        to_return(status: 200,
                  body: {
                    "values" => select_values,
                  }.to_json,
                  headers: {})

      get :index, params: { request_identifier: generate_request_identifier() }
      expect(response).to have_http_status(:success)
      expect(response).to render_template(:index)
      # Extract the select value names as an array of strings.
      select_value_names = select_values.map {|v| v['name']}
      expect(response.body).to include(select_value_names)
    end
  end

相关说明,如果您要针对页面内容进行 运行 测试,您可能需要考虑使用验收测试框架,例如 Capybara,它与 Rspec 集成得很好.