Testing models
According to Rails conventions, is in the models that we should put the logic related with the data persistence, therefore the most common tests to do is the model attributes validations, the persistence actions and the queries.
In this post we are going to split our test focused on this model roles, first we have to configure the Rails project to work with rspec, give a look to this post.
Following Rails and Rspec conventions for each model X's we should create a test file in the folder spec/models/modelname_spec.rb, the general structure of the test file is the following:
require 'rails_helper'
RSpec.describe Post, type: :model do
describe 'Validations' do
...
end
describe 'Relations' do
...
end
describe 'Callbacks' do
...
end
end
Validations
The model validations basically evaluates the state of the objects before it gets persisted, in the following code we'll see how to use shoulda-matcher for specific validations:
# post.rb
class Post < ApplicationRecord
validates :title, :description, presence: true
validates_numericality_of :size, greater_than: 20
...
end
# post_spec.rb
...
describe 'Validations' do
it { should validate_presence_of :title }
it { should validate_presence_of :description }
it { should validate_numeracility_of(:size).is_greater_than(20) }
end
Relations
The model relations are the ones that indicates how the database is designed and how are the relations between the objects of distinct class.
#post.rb
class Post < ApplicationRecord
...
has_many :comments
belongs_to :user
has_many :mentions, through: :comments
has_and_belongs_to_many :types
accepts_nested_attributes_for :comments, allow_destroy: true
end
#post_spec.rb
...
describe 'Relations' do
it { should have_many :comments }
it { should belong_to :user }
it { should have_many(:mentions).through(:comments) }
it { should have_and_belong_to_many :types }
it { should accept_nested_attributes_for(:comments).allow_destroy(true) }
end
Custom methods
Normally used to modify the state of the object, we will test, given certain parameters return an specific response.
# post.rb
class Post < ApplicationRecord
before_save :set_type
private
def set_type
type = 'some' unless self.comments.length.zero?
end
end
#post_spec.rb
...
describe 'Callbacks' do
it 'should set type some' do
post = Post.new
comment = Comment.new
post << comment
post.save
post.reload
expect(post.type).to eq 'some'
end
end
With this we have conclude this model tests section, any acotation, correction or doubt you can comment below.