【问题标题】:RSpec throws weird fault textRSpec 抛出奇怪的错误文本
【发布时间】:2020-03-26 11:10:12
【问题描述】:

我想用 RSpec 测试我的 board_controller。我坚持对 JSON 响应进行同等验证。

这里是简单的boards_controller_spec.rb

require "rails_helper"

RSpec.describe Api::V1::BoardsController, type: :request do
  context "#index" do
    it "must return data" do
      get "/api/v1/boards"
      expect(response.body).to include_json(
        data: [
          id: (should be_kind_of Integer),
          link: (should be_kind_of String),
        ],
      )
    end
  end
end

这是我的 boards_controller.rb,它只有 #index#show 方法。

module Api::V1
  class BoardsController < ApplicationController

    def index
      @boards = Board.all

      render json: @boards
    end

    def show
      @board = Board.find(params[:id])

      render json: @board
    end

    private

    def set_board
      @board = Board.find(params[:id])
    end

    def board_params
      params.require(:board).permit(:link)
    end
  end
end

在 host:3000/api/v1/boards 页面上我有这个 JSON 响应:

[
  {
    "id": 1,
    "link": "mzdbQBiKYk",
    "created_at": "2020-03-23T21:29:14.335Z",
    "updated_at": "2020-03-23T21:29:14.335Z"
  },
  {
    "id": 2,
    "link": "ZkbspsYIPz",
    "created_at": "2020-03-23T21:29:14.347Z",
    "updated_at": "2020-03-23T21:29:14.347Z"
  }
]

所以我的目标是检查 id 是否为整数且链接是否为字符串,但是当我尝试运行测试时出现此错误:

Failures:

  1) Api::V1::BoardsController#index must return data
     Failure/Error: id: (should be_kind_of Integer),
       expected #<Api::V1::BoardsController:0x0000561c114a6e28 @_routes=nil, @_request=nil, @_response=nil> to be a kind of Integer
     # ./spec/requests/boards_controller_spec.rb:9:in `block (3 levels) in <top (required)>'

这里有什么问题? Boards 是用种子创建的(只为板子生成随机链接),因为我不需要这个模型的 create 方法。

【问题讨论】:

  • 你有一个期望这个期望。这没有任何意义。你只需要有一个期望。事实上,更准确地说,您的测试失败了,因为您实际上是在说:expect(subject).to be_kind_of(Integer)
  • 那行应该更像:id: kind_of(Integer)
  • 谢谢你,@TomLord!但是expect(id).to kind_of(Integer) 会引发另一个错误。 id is not available from within an example....。首先我需要从 JSON 响应中获取该 ID?
  • 这不是我说要写的
  • 我说你不​​需要期望中的期望。整个测试只需要写一次“expect”即可。

标签: ruby-on-rails ruby rspec


【解决方案1】:

includes_json 匹配器用于匹配 JSON 的实际值。

RSpec.describe Api::V1::BoardsController, type: :request do
  context "#index" do
    it "must return data" do
      get "/api/v1/boards"
      expect(response.body).to include_json(
        data: [
          id: 1,
          link: "mzdbQBiKYk"
        ]
      )
    end
  end
end

检查您在测试设置阶段设置的记录的值,如果您正在使用该垃圾,请检查您的固定装置。

如果你想检查你需要手动遍历 JSON 的类型:

RSpec.describe Api::V1::BoardsController, type: :request do
  let(:json) { JSON.parse(response.body) }
  context "#index" do
    it "must return data" do
      get "/api/v1/boards"
      expect(json["data"].first["id"]).to be_kind_of Integer
    end
  end
end

但这并不是一个很好的测试,因为您实际上可以测试它是否包含正确的数据。 此外,您还有一个奇怪的控制器规范和request spec 的统一组合。请求规范应如下所示:

RSpec.describe 'Boards API V1', type: :request do
  describe "GET /api/v1/boards" do
    let!(:boards) do
       # @todo setup data for the test
    end

    it "must return data" do
      get "/api/v1/boards"
      expect(response.body).to include_json(
        data: [
          id: boards.first.id
          link: boards.first.link
        ]
      )
    end 
  end
end

一个好的请求规范描述了您正在测试的 HTTP 端点。不是底层控制器。

【讨论】:

  • 感谢您对示例的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-25
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 2015-10-25
  • 2020-10-23
相关资源
最近更新 更多