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:

results matching ""

    No results matching ""