Hello I am learning to test rails application using rspec. I am testing bank application where transaction belongs to account. I am testing the Transaction model. It's code is as follows: Transaction.rb:
class Transaction < ApplicationRecord
validates :amount, presence: true, numericality: { only_integer: true,
greater_than: 0 }
after_create :update_balance
belongs_to :account
def update_balance
if transaction_type == 'debit'
account.current_balance -= amount
else
account.current_balance += amount
end
end
end
And it's spec is as follows:
require 'rails_helper'
RSpec.describe Transaction, type: :model do
it { should belong_to(:account)}
subject {
described_class.new(amount: 60, transaction_type: 'credit',
id: 1,
created_at: DateTime.now, updated_at: DateTime.now,
account_id: 1)
}
it 'is valid with valid attributes' do
expect(subject).to be_valid
end
it 'is not valid without amount' do
subject.amount = nil
expect(subject).to_not be_valid
end
it 'is not valid without transaction type' do
subject.transaction_type = nil
expect(subject).to_not be_valid
end
it 'is not valid without created_at date' do
subject.created_at = nil
expect(subject).to_not be_valid
end
it 'is not valid without updated_at date' do
subject.updated_at = nil
expect(subject).to_not be_valid
end
it 'is not valid without transaction id' do
subject.id = nil
expect(subject).to_not be_valid
end
it 'is not valid without account id' do
subject.id = nil
expect(subject).to_not be_valid
end
end
I used shoulda gem for association. However when I run this test, it throws error as ' account must exist', even though I have added the association.
Error:
.F......
Failures:
1) Transaction is valid with valid attributes
Failure/Error: expect(subject).to be_valid
expected #<Transaction id: 1, transaction_type: "credit", amount: 0.6e2, created_at: "2018-11-13 10:33:13", updated_at: "2018-11-13 10:33:13", account_id: 1> to be valid, but got errors: Account must exist
# ./spec/models/transaction_spec.rb:12:in `block (2 levels) in <top (required)>'
Finished in 0.02937 seconds (files took 0.77127 seconds to load)
8 examples, 1 failure
Can anybody please help to understand what is it I am doing wrong?
P.S: Transaction table has account_id column for the association.
Thanks inadvance.
In Rails 5, associations defined as belongs_to
are required by default. So when you are checking expect(subject).to be_valid
, the valid?
call is returning false because you don't have an account set.
Your approach to get your tests working will then depend on what you want your application's object model to look like.
If a transaction can exist without an account, then set up your association that way:
class Transaction < ApplicationRecord
belongs_to :account, optional: true
end
However, I think it's more likely that a transaction without an account doesn't make sense. So your current test is actually right – when you're testing an accountless transaction, it's not valid.
In this case, you can set up your test subject accordingly:
RSpec.describe Transaction, type: :model do
let(:account) { Account.new }
subject {
described_class.new( ..., account: account)
}
...
end