Testing Models with Shoulda Matchers
Your coworker at Reading Meow has already started building out some of the basic tables needed for the app using rails g model
commands. Specifically, they've created...
- User
- Cat
- CatReadingWrangler
- Library
- Contact
Your task: add tests to confirm that all of our models have the appropriate associations.
First, let's run our test suite to get started
Run bundle exec rspec
to see what tests fail or are pended.
.*****...
Pending: (Failures listed here are expected and do not affect your suite's status)
1) CatReadingWrangler add some examples to (or delete) /Users/ni_lo/Code/talks/rspec/reading_meow/spec/models/cat_reading_wrangler_spec.rb
# Not yet implemented
# ./spec/models/cat_reading_wrangler_spec.rb:4
2) Cat add some examples to (or delete) /Users/ni_lo/Code/talks/rspec/reading_meow/spec/models/cat_spec.rb
# Not yet implemented
# ./spec/models/cat_spec.rb:4
3) Contact add some examples to (or delete) /Users/ni_lo/Code/talks/rspec/reading_meow/spec/models/contact_spec.rb
# Not yet implemented
# ./spec/models/contact_spec.rb:4
4) Library add some examples to (or delete) /Users/ni_lo/Code/talks/rspec/reading_meow/spec/models/library_spec.rb
# Not yet implemented
# ./spec/models/library_spec.rb:4
5) User add some examples to (or delete) /Users/ni_lo/Code/talks/rspec/reading_meow/spec/models/user_spec.rb
# Not yet implemented
# ./spec/models/user_spec.rb:4
Finished in 0.04619 seconds (files took 4.17 seconds to load)
9 examples, 0 failures, 5 pending
Great... we have a whole bunch of model tests ready for us to implement!
How can we test our associations?
Enter Shoulda Matchers!
Shoulda Matchers is a gem that allows you to test your associations as well as validations for your models. Check out the documentation here: https://github.com/thoughtbot/shoulda-matchers
Note -- to use Shoulda Matchers, we have to add some additional configuration to rails_helper (already done)
Add a failing test
Let's start with our User
and Cat
model specs.
- Navigate to
spec/models/cat_spec.rb
- Delete the pending test, and add...
# in spec/models/cat_spec.rb
RSpec.describe Cat, type: :model do
it { is_expected.to belong_to(:user) }
end
# Add the below to your user model spec
RSpec.describe User, type: :model do
it { is_expected.to have_one(:cat) }
end
Run your tests
Watch them fail... now modify your User
and Cat
model classes to make them pass!
class User < ApplicationRecord
has_one :cat
end
class Cat < ApplicationRecord
belongs_to :user
end
Your tests should now pass!
Testing Validations
Let's say we do not want to allow a cat reading wrangler to exist without a library card. Let's add a test to validate that the library_card_number
field is not nil
for any CatReadingWrangler
instance.
Practice Time (5 mins)
- Add failing tests and then implement the remaining associations
Our desired associations...
- Cats and Cat reading wranglers are users and have a
user_id
foreign key - We only ever expect a user to have one cat or cat reading wrangler
- Contacts have a polymorphic association to something that is 'contactable'
- Both users and libraries are contactable
Diff with the solutions
Solutions are in our testing_models_solutions
branch. Diff that branch and with how far you made it in the start branch to see what more is needed to make your tests pass.
Commits showing progression through the above exercises:
- Adding failing association tests view on github