Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails Rspec-如何设置多态性有很多关联_Ruby On Rails_Rspec - Fatal编程技术网

Ruby on rails Rails Rspec-如何设置多态性有很多关联

Ruby on rails Rails Rspec-如何设置多态性有很多关联,ruby-on-rails,rspec,Ruby On Rails,Rspec,通过多态关联,我有一个属于另一个模型(事件)的模型(付款) 某些测试失败,因为所有者模型(事件)在验证中由支付模型访问,但事件返回nil。当直接在浏览器中测试应用程序时,所有功能都可以正常工作。 我在下面的payment.rb中添加了更多的注释 我试着在工厂里定义关联,但没有成功 在规范中建立此关联的最佳方法是什么 # models/event.rb class Event < ApplicationRecord has_many :payments, as: :payable,

通过多态关联,我有一个属于另一个模型(事件)的模型(付款)

某些测试失败,因为所有者模型(事件)在验证中由支付模型访问,但事件返回nil。当直接在浏览器中测试应用程序时,所有功能都可以正常工作。 我在下面的
payment.rb
中添加了更多的注释

我试着在工厂里定义关联,但没有成功

在规范中建立此关联的最佳方法是什么

# models/event.rb

class Event < ApplicationRecord

  has_many :payments, as: :payable, dependent: :destroy

end
输出


# bundle exec rspec spec/models/payment_spec.rb

Randomized with seed 42748

Payment
  Association
    should belong to payable required: true (FAILED - 1)
  Validation
    #amount_is_valid
      not charge more than event balance (FAILED - 2)

Failures:

  1) Payment Association should belong to payable required: true
     Failure/Error: if amount.to_i > payable.balance.to_i
     
     NoMethodError:
       undefined method `balance' for nil:NilClass
     # ./app/models/payment.rb:9:in `amount_is_valid'
     # ./spec/models/payment_spec.rb:23:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:80:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:79:in `block (2 levels) in <top (required)>'
     # ./spec/spec_helper.rb:108:in `block (2 levels) in <top (required)>'

  2) Payment Validation #amount_is_valid not charge more than event balance
     Failure/Error: if amount.to_i > payable.balance.to_i
     
     NoMethodError:
       undefined method `balance' for nil:NilClass
     # ./app/models/payment.rb:9:in `amount_is_valid'
     # ./spec/models/payment_spec.rb:39:in `block (4 levels) in <top (required)>'
     # ./spec/rails_helper.rb:80:in `block (3 levels) in <top (required)>'
     # ./spec/rails_helper.rb:79:in `block (2 levels) in <top (required)>'
     # ./spec/spec_helper.rb:108:in `block (2 levels) in <top (required)>'

Top 2 slowest examples (0.29972 seconds, 71.6% of total time):
  Payment Association should belong to payable required: true
    0.28796 seconds ./spec/models/payment_spec.rb:18
  Payment Validation #amount_is_valid not charge more than event balance
    0.01176 seconds ./spec/models/payment_spec.rb:32

Finished in 0.4186 seconds (files took 4.31 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./spec/models/payment_spec.rb:18 # Payment Association should belong to payable required: true
rspec ./spec/models/payment_spec.rb:32 # Payment Validation #amount_is_valid not charge more than event balance


你的第一次考试并没有在你认为的地方失败。下一行失败,
应属于(:应付)

您正在设置
payment
,但正在测试将是
payment.new

is_expected.to belong_to(:payable)
相当于

expect(subject).to belong_to(:payable)
由于您没有定义的
主题
这是

expect(Payment.new).to belong_to(:payable)
付款。新的
没有定义
应付款
,因此
金额有效
验证错误

要解决此问题,请直接测试
付款
。我建议你在学习RSpec时远离
主题
。而且您不必设置
payment.event
,它已经在工厂中设置好了

describe 'Association' do
  expect(payment).to belong_to(:payable)
end
但我不知道有谁属于匹配者。您不应该直接检查实现,而应该检查其行为。您想要的行为是用于
payment.payment
以返回
payment

describe '#payable' do
  it 'is a Payable' do
    expect(payment.payable).to be_a(Payable)
  end
end

第二个失败是因为您错误地初始化了付款。您正在传入
payment\u id:event.id
,但未设置
payment\u type
。如果没有
payment\u type
它就不知道ID是用于哪个类的

相反,直接传递对象

let!(:payment) { 
  FactoryBot.build(:payment, 
    amount: 300,
    method: 'cash', 
    payer: user,
    payable: event, 
    status: 1,
  )
}

一些更一般的清理

  • let将始终运行块,无论是否使用。除非您特别需要,否则使用
    let
    ,块将根据需要运行
  • 您希望存在
    应付款
    ,因此请验证
    应付款
    的存在
  • 使用内置的金额

谢谢非常感谢您的深入回复和额外建议。我的规格现在通过了。有一件事-忘了在原来的帖子中提到,我使用的是
shoulda matchers
gem,它提供了
属于
助手。@orangesoda不客气。试试rubocop rspec,它会发现很多问题,就像你遇到的一样。
describe 'Association' do
  expect(payment).to belong_to(:payable)
end
describe '#payable' do
  it 'is a Payable' do
    expect(payment.payable).to be_a(Payable)
  end
end
let!(:payment) { 
  FactoryBot.build(:payment, 
    amount: 300,
    method: 'cash', 
    payer: user,
    payable: event, 
    status: 1,
  )
}
class Payment < ApplicationRecord

  belongs_to :payable, polymorphic: true
  validates :payable, presence: true

  validates :amount, numericality: {
    less_than_or_equal_to: balance,
    message: "must be less than or equal to the balance of #{balance}"
  }
end
require 'rails_helper'

RSpec.describe Payment, type: :model do
  let(:event) {
    create(:event, event_type: 'test', total: 10000, balance: 10000)
  }
  let(:user) { create(:user) }
  let(:payment) {
    build(:payment, 
      amount: 300,
      method: 'cash', 
      payer: user,
      payable: event,
      status: 1
    )
  }

  # It's useful to organize tests by method.
  describe '#payable' do
    it 'is a Payable' do
      expect(payment.payable).to be_a(Payable)
    end
  end

  describe '#amount' do
    # Contexts also help organize and name your tests.
    context 'when the amount is higher than the payable balance' do
      # This code will run before each example.
      before {
        # Rather than hard coding numbers, make your tests relative.
        # If event.balance changes the test will still work.
        payment.amount = payment.payable.balance + 1
      }
    
      it 'is invalid' do 
        expect(payment.valid?).to be false
        expect(payment.errors[:amount]).to include("must be less than or equal to")
      end
    end
  end
end