【问题标题】:RSpec Couldn't find with 'id'=RSpec 找不到'id'=
【发布时间】:2016-11-21 06:46:19
【问题描述】:

我正在编写 RSpec 控制器测试,但遇到了以下问题。

这种关系是发票属于一个采购,一个采购有许多发票。

我的控制器有:

class InvoicesController < ApplicationController
  def index
    @invoices = Invoice.all
  end

  def new
    @purchase = Purchase.find(params[:purchase])
    @invoice = Invoice.new(:purchase_id => params[:purchase])
  end

我的工厂有:

FactoryGirl.define do
  factory :invoice do |f|
    sequence(:id) { |number| number }
    f.purchase_id {rand(1..30)}
    f.number { FFaker::String.from_regexp(/\A[A-Za-z0-9]+\z/) }
    f.terms { FFaker::String.from_regexp(/\A[A-Za-z0-9\s]+\z/) }
    f.currency { FFaker::String.from_regexp(/\A[A-Z]+\z/) }
    f.total_due {'25000.00'}
    f.current_balance {'12500.00'}
    f.due_date { FFaker::Time.date }
    f.notes { FFaker::HipsterIpsum.paragraph }
    f.status {[:open, :paid, :canceled].sample}
    purchase
  end

  factory :invalid_invoice, parent: :invoice do |f|
    f.status nil
  end
end

我的控制器规格(只是有问题的部分)有:

describe "GET new" do
    it "assigns a new invoice to @invoice" do
      invoice = FactoryGirl.create(:invoice)
      get :new
      expect(assigns(:invoice)).to_not eq(invoice)
    end

    it "renders the :new template" do
      get :new
      expect(response).to render_template :new
    end
  end

在我的路线中,我有:

purchases GET                       /purchases(.:format)                        purchases#index
                                 POST                      /purchases(.:format)                        purchases#create
                    new_purchase GET                       /purchases/new(.:format)                    purchases#new
                   edit_purchase GET                       /purchases/:id/edit(.:format)               purchases#edit
                        purchase GET                       /purchases/:id(.:format)                    purchases#show
                                 PATCH                     /purchases/:id(.:format)                    purchases#update
                                 PUT                       /purchases/:id(.:format)                    purchases#update
                                 DELETE                    /purchases/:id(.:format)                    purchases#destroy

invoices GET                       /invoices(.:format)                         invoices#index
                                 POST                      /invoices(.:format)                         invoices#create
                     new_invoice GET                       /invoices/new(.:format)                     invoices#new
                    edit_invoice GET                       /invoices/:id/edit(.:format)                invoices#edit
                         invoice GET                       /invoices/:id(.:format)                     invoices#show
                                 PATCH                     /invoices/:id(.:format)                     invoices#update
                                 PUT                       /invoices/:id(.:format)                     invoices#update
                                 DELETE                    /invoices/:id(.:format)                     invoices#destroy

当我运行测试时,我得到了这个:

1) InvoicesController GET new assigns a new invoice to @invoice
     Failure/Error: get :new
     ActiveRecord::RecordNotFound:
       Couldn't find Purchase with 'id'=
     # ./app/controllers/invoices_controller.rb:7:in `new'
     # ./spec/controllers/invoices_controller_spec.rb:38:in `block (3 levels) in <top (required)>'

  2) InvoicesController GET new renders the :new template
     Failure/Error: get :new
     ActiveRecord::RecordNotFound:
       Couldn't find Purchase with 'id'=
     # ./app/controllers/invoices_controller.rb:7:in `new'
     # ./spec/controllers/invoices_controller_spec.rb:43:in `block (3 levels) in <top (required)>'

这是来自 test.log 的 sn-p

[1m[36m (0.1ms)[0m [1mRELEASE SAVEPOINT active_record_1[0m [1m[35m (0.1ms)[0m SAVEPOINT active_record_1 [1m[36mSQL (0.3ms)[0m [1mINSERT INTO "purchases" ("id", "vendor_id", "order_number", "status", "notes", "tradegecko_url", "created_at", "updated_at") 值($1, $2, $3, $4, $5, $6, $7, $8) 返回 "id"[0m [["id", 4], ["vendor_id", 4], ["order_number", "zzz"], [“状态”,“取消”],[“注释”,“牛仔短裤陈词滥调威廉斯堡生牛仔布在信使包上放了一只鸟。Shoreditch keytar Brooklyn lomo 早午餐。Mcsweeney 的 Cosby 毛衣 +1 PBR Austin biodiesel freegan。”],[ "tradegecko_url", "http://gorczany.info"], ["created_at", "2016-07-19 14:51:00.616108"], ["updated_at", "2016-07-19 14:51:00.616108"]] [1m[35m (0.1ms)[0m 释放保存点 active_record_1 [1m[36m (0.1ms)[0m [1mSAVEPOINT active_record_1[0m [1m[35mSQL (0.3ms)[0m INSERT INTO "invoices" ("id", "purchase_id", "number", "terms", "currency", "total_due", "current_balance", "due_date", "notes ", "status", "created_at", "updated_at") 值 ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) 返回 "id" [["id", 4], ["purchase_id", 4], ["number", "dd"], ["terms", "TT"], ["currency", "MM"], ["total_due", "25000.0"] , ["current_balance", "12500.0"], ["due_date", "2015-11-13"], ["notes", "Scenester Carles cred quinoa fixie put a bird on it Four Loko next level. Biodiesel Vice Wayfarers Sustainable早午餐屠夫 locavore。Keytar 副下一级树桩镇 Rerry Richardson。"], ["status", "canceled"], ["created_at", "2016-07-19 14:51:00.619066"], ["updated_at", " 2016-07-19 14:51:00.619066"]] [1m[36m (0.1ms)[0m [1mRELEASE SAVEPOINT active_record_1[0m InvoicesController#new 作为 HTML 处理 [1m[35mPurchase Load (0.3ms)[0m SELECT "purchases".* FROM "purchases" WHERE "purchases"."id" = $1 LIMIT 1 [["id", nil]] Completed 404 Not Found in 2ms (ActiveRecord: 0.3ms)

我认为问题在于创建了工厂关联,但没有保存。所以当 purchase.id 被调用时,它会返回 nil。

【问题讨论】:

  • 此错误表明您正在执行此操作:ModelXYZ.find(&lt;id&gt;) 并且 id 未保留。 (RecordNotFound) 请发布您的路线以帮助我们。
  • 感谢您花时间尝试帮助我。我明白错误在说什么,我不知道如何解决它。在示例之前,我尝试使用 FactoryGirl 创建购买记录,但没有成功,我仍然遇到同样的错误。

标签: ruby-on-rails rspec-rails


【解决方案1】:

您正在尝试在new 操作中加载购买:

  def new
    @purchase = Purchase.find(params[:purchase])
    @invoice = Invoice.new(:purchase_id => params[:purchase])
  end

但在您的测试中,您没有传递 :purchase 参数(我猜应该是 :purchase_id)!

【讨论】:

  • 对。在实际应用中,只能从购买创建发票,因此将 purchase_id 传递给正在创建的发票。在测试中,我尝试在示例之前手动创建购买,我尝试使用 FactoryGirl 在示例之前创建购买。我仍然无法将 purchase_id 传递给新发票。
  • 好吧..也许再努力一点?那么你到底尝试了什么?
  • 在运行测试时查看 log/test.log 的内容也可能会有所帮助
  • 哈哈!我一直在努力。还在做。
  • 我添加了一个 test.log sn-p。关联的购买由 FactoryGirl 生成,但没有保存,所以当调用 purchase.id 时它返回 nil。
【解决方案2】:

工厂中声明的关联没有持续存在,导致 Purchase.id 的值为 nil。

所以在尝试回调之前,回调之后,特征之后,我放弃了使用 FactoryGirl 的自动生成的关联。

最后这就是我必须做的:

我从工厂中删除了所有声明的关联,然后手动完成,规范中的编辑代码:

describe "GET new" do

    it "assigns a new invoice to @invoice" do
      invoice = FactoryGirl.create(:invoice)
      get :new, purchase: FactoryGirl.create(:purchase)
      expect(assigns(:invoice)).to_not eq(invoice)
    end

    it "renders the :new template" do
      get :new, purchase: FactoryGirl.create(:purchase)
      expect(response).to render_template :new
    end
  end

我希望这对遇到此问题的其他人有所帮助。

【讨论】:

  • f.purchase_id {rand(1..30)} 我认为这是您的问题或部分问题。您的工厂正在创建一个随机购买 ID
  • 您可以将自动生成的purchase 添加回您的工厂,然后像这样将您的呼叫更改为get 吗? get :new, purchase: invoice.purchase
  • Doon - 我尝试删除该行,但当它不起作用时,我将其更改为序列,仍然是同样的错误。
  • 克里斯,我之前确实尝试过,但遇到了未定义的方法“购买”错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
相关资源
最近更新 更多