Rspec + Rails: Testing models

Rspec + Rails: Testing models

enmanuelm19@gmail.com2018-09-08 14:43:15 UTC

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.


Share