Ruby on rails Rails Rspec-如何设置多态性有很多关联
通过多态关联,我有一个属于另一个模型(事件)的模型(付款) 某些测试失败,因为所有者模型(事件)在验证中由支付模型访问,但事件返回nil。当直接在浏览器中测试应用程序时,所有功能都可以正常工作。 我在下面的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,
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