我试图为已经实施的代码进行测试。我是单元测试和RSpec的新手,在我的生活中无法弄清楚这个错误。基本上,我试图验证JSON是否被发送到正确的端点。我想我已经创建了我需要的所有属性,但我不断得到同样的错误。这是错误和我的代码。它显然与从另一个模型表中包括城市有关,但我不确定它为什么抱怨?
这是测试。
ncap2 -s 'valf=double(valf)' nc_data.nc nc_data.nc
这是我的错误消息
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",
)
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["city"]).to eql(location.city)
end
end
end
这是我的控制器
/api/retailers GET /api/retailers Returns JSON for retailers
Failure/Error: location.city
NoMethodError:
undefined method `city' for nil:NilClass
# ./app/models/retailer.rb:8:in `city'
这是我的模特
class Api::RetailersController < ApiController
def index
@retailers = Retailer.all
render json: @retailers, methods: [:city]
end
end
任何帮助都会很棒。我真的很难过这个问题。如果有任何其他信息是必要的,请告诉我
答案 0 :(得分:1)
您的Retailer
模型与location
有关系。
你也有一个city
方法,正在查看location
def city
location.city
end
现在,它包含在您的控制器中:
render json: @retailers, methods: [:city]
现在,在测试中,您创建了location
和retailer
:
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",
)
但这两者在任何方面都无关。
因此,在测试中,您向控制器的get
操作发送了index
个请求,
get "/api/retailers.json"
这会尝试获取零售商的city
,这是上述方法。但请记住,该方法会尝试获取location.city
但是您的retailer
没有location
,因为它尚未与任何内容相关联......所以,location
此处为nil
然后,当您在city
(即零)上致电location
时,您正在city
上呼叫nil
这是错误的来源:
NoMethodError:
undefined method `city' for nil:NilClass
# ./app/models/retailer.rb:8:in `city'
编辑(修复):
在测试中添加创建为零售商位置的位置,如下所示:
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 # Add location as location here.
)
答案 1 :(得分:1)
city
方法使用Retailer
的位置,该位置未针对您创建的位置设置。
要解决此问题,只需将location
关联分配给Retailer
:
retailer = Retailer.create!(
name: "Good Coffee Co.",
description: "Hipster Good",
image_url: "http://www.example.com/foo_bar.jpg",
location: location
)
答案 2 :(得分:1)
您实际上从未在零售商和地点之间建立关联。因此,当调用retailer#city
时,位置为零。
您可能希望首先更改您的方法以优雅地处理nil,除非您的业务逻辑不允许没有位置的零售商:
class Retailer < ActiveRecord::Base
has_one :location
has_many :retailer_timeslots
has_many :timeslots, through: :retailer_timeslots
def city
location.city if location
end
end
更优雅的方法是使用Module#delegate
:
class Retailer < ActiveRecord::Base
has_one :location
has_many :retailer_timeslots
has_many :timeslots, through: :retailer_timeslots
delegate :city, to: :location, allow_nil: true
end
这应该将规格从破坏变为失败。
要修复规范,您需要设置两者之间的关系:
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 # !!!!!
)