How to test concerns in Ruby on Rails

Ats
3 min readNov 12, 2023

--

I had a chance to write tests for methods in concerns last week. This is the note about what I did.

Photo by Nguyen Dang Hoang Nhu on Unsplash

First of all

I’m using rspec and going to talk about rspec

Background

I have refactored Ruby on Rails models for the last few weeks. Then I made some concerns in our model layer to put common methods. I’ve written a lot of test codes in Ruby on Rails because I love test code. However, I’ve never written any for concerns before. So I was like “It’s a good opportunity to try.” Then I started to research how to do that.

What I did

I found a few articles about testing concerns like below

Then I realized I could categorize most of them into 2 types. The first one is creating a dummy object which includes concerns and testing the object. The other one is creating sharable behavior tests and testing the behavior with real objects. I can see points in both approaches. The first one is more about testing their concerns as isolating from others. The other is more focused on the behavior in a real context.

In terms of unit testing, I think the first approach makes more sense to me because I can focus on the concern’s specification more than the other. However, in my opinion, I don’t think it’s a good idea to create a dummy object only for testing because the dummy object could be far from a real use case and it could happen suddenly without anyone’s aware. At worst, the concern could work only in a test environment. So I decided to go with the second approach and try to stick with Rails way as much as possible.

I checked rails_helper.rb and rspec_helper.rb quickly and found what I could use in rails_helper.rb

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the — pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
Dir[Rails.root.join(‘spec’, ‘support’, ‘**’, ‘*.rb’)].sort.each { |f| require f }

After reading the section, I thought it could be a good idea to use the support directory to share the concern’s behavior tests.

I created spec/support/concerns/ directory and put shared examples in the file. Let’s say we have hashidable concern. Then I create pec/support/concerns/hashidable_spec.rb so that Ruby on Rails treats the file as spec files and I can use the shared examples everywhere. The following code is just an example.

require 'spec_helper'

shared_examples_for 'hashidable' do
let(:model) { create(described_class.to_s.underscore) }

describe '#encoded_id' do
subject { model.encoded_id }

it { is_expected.to eq('hogehoge') }
end
end

Then I execute it in the model tests which include the concern. Let’s say the model is User

require 'rails_helper'

describe Coach, type: :model do
it_behaves_like 'hashidable'

...other model specs here...
end

Then finally, I could test my concerns method in real contexts.

That’s it!

--

--

Ats
Ats

Written by Ats

I like building something tangible like touch, gesture, and voice. Ruby on Rails / React Native / Yocto / Raspberry Pi / Interaction Design / CIID IDP alumni

No responses yet