RSpec - 类型错误 - 没有将String隐式转换为Integer

时间:2016-04-20 18:03:01

标签: ruby-on-rails ruby rspec

我正在尝试将测试设为绿色并且我收到此错误。即使我撬开代码,它也会显示正在返回一个字符串,所以我不知道为什么测试不会变绿。这是我的测试和错误澄清。我认为这是人们的常见错误。

这是我的测试 -

require "rails_helper"

RSpec.describe "/api/retailers" do

describe "GET /api/retailers" do
it "Returns JSON for retailers" do

  location = Location.create!(
    city: "Portland",
    street_1: "Cherry",
    state: "Oregon",
    zip: "49490"
  )

  retailer = Retailer.create!(
    name: "Good Coffee Co.",
    description: "Hipster Good",
    image_url: "http://www.example.com/foo_bar.jpg",
    location: location
  )

  get "/api/retailers.json"

  expect(response).to be_success
  json = JSON.parse(response.body)

  expect(json["name"]).to eql("Good Coffee Co.")
  expect(json["description"]).to eql("Hipster Good")
  expect(json["image_url"]).to eql("http://www.example.com/foo_bar.jpg")
  expect(json["location"]).to eql(location.city)
end
end
end

这是我的错误消息 -

/api/retailers GET /api/retailers Returns JSON for retailers
 Failure/Error: expect(json["name"]).to eql("Good Coffee Co.")

 TypeError:
   no implicit conversion of String into Integer
 # ./spec/requests/retailers_spec.rb:28:in `[]'
 # ./spec/requests/retailers_spec.rb:28:in `block (3 levels) in <top (required)>'

2 个答案:

答案 0 :(得分:3)

看起来您正在点击一个索引端点,该端点正在返回一系列零售商,在您的情况下是一个拥有单个零售商的阵列。要访问它,您需要选择数组中的第一个对象,然后进行比较:

expect(json[0]['name']).to eq('Good Coffee Co.')

在类似的说明中,您应该使用letbefore来设置测试。遵循rspec约定不仅可以使您的代码更具可读性,而且更易于维护。我已经在下面更改了样式,以便我通常如何布置测试。这些只是当然的建议,并对控制器的命名和范围做出一些假设。

require "rails_helper"

RSpec.describe Api::RetailersController do

  # /api/retailers
  describe '#index' do
    let!(:location) {
      Location.create!(
        city: "Portland",
        street_1: "Cherry",
        state: "Oregon",
        zip: "49490"
      )
    }

    let!(:retailer) {
      Retailer.create!(
        name: "Good Coffee Co.",
        description: "Hipster Good",
        image_url: "http://www.example.com/foo_bar.jpg",
        location: location
    )

    before(:each) do
      get :index, format: :json
      json = JSON.parse(response.body)
    end

    it 'Returns a status 200' do
      expect(response).to be_success
    end
    it 'Returns a JSON list of retailers' do
      expect(json.length).to eq(1)
    end

    # I would probably only check these in the show action
    # unless needing different data on index
    it 'Contains a name attribute' do
      expect(json[0]['name']).to eq('Good Coffee Co.')
    end
    it 'Contains a description attribute' do
      expect(json[0]['description']to eq('Hipster Good')
    end
    it 'contains an image_url attribute' do
      expect(json[0]['image_url']).to eq('http://www.example.com/foo_bar.jpg')
     end
     it 'contains a location attribute' do 
       expect(json[0]['location']).to eq(location.city)
     end
   end
 end

答案 1 :(得分:2)

正如评论中所提到的,问题是JSON对象返回一个对象数组。因此,正确的测试期望如下:

expect(json.first["name"]).to eq("Good Coffee Co.")
expect(json.first["description"]).to eq("Hipster Good")
expect(json.first["image_url"]).to eq("http://www.example.com/foo_bar.jpg")
expect(json.first["city"]).to eq("Portland")