As developers, tackling complex problems in bits and modules is common practice. Tests performed in the different parts of our application, in isolation, are called unit testing. These are usually done on the smallest part of the application.
By the end of this article, you should be comfortable working with Model and Helper Specs.
Working With Rails Model Specs
In my opinion, model specs are the most important test you can run in your application. They are easy to work with, mostly because, unlike controllers there is no request/response cycle to worry about - there is nothing like rendering a template.
As a beginner, model specs are the easiest to take on, and add a lot of value. They are fairly straight forward, but I’m going to share a few pointers that will help you get past the most common stumbling blocks:
- There may be times you need to #reload after making changes in the database to ensure you’re working with a fresh copy of the database. This won’t happen all the time, so you certainly shouldn’t overuse it.
- Get comfortable in understanding the difference between the lazy-executing #let versus eagerly-executing #let!. The first doesn’t actually get executed until it’s called, while #let! forces it to happen right away.
- Another thing people often get confused about is how to write tests for Scopes. Scopes:match_array works with ActiveRecord::Relations.
How to Test Associations & Validations
Some complex code can be written to allow you to poke around in Rails internals, in order to figure out your test expectations. But a far easier way to do this is to use a popular third-party library by thoughtbot called shoulda-matchers. This library gives you a lot of useful matchers to play with. For example; have_many, validate_presence_of.
Did you notice a slight difference there? It says “have_many” not “has_many” and that's because it’s a matcher meant to be used with an expectation. So we would expect users to “have_many” posts. In the definition we say, has_many :posts but in our expectations, we say — we expect users to have_many orders. The same applies to validation.
Place the code below at the bottom of spec/rails_helper.rb
I encourage you to take a look at the shoulda-matchers documentation, there are great examples there that will guide you in writing yours.
The examples below will give you better insights on using shoulda-matchers for both your validations and association testing.
Tests for Validations Above
Working with ActiveRecord Test Doubles:
It used to be part of the official RSpec but moved out to be a separate gem. This tool gives us two additional methods to use: mock-model and stub-model.
The mock-model is used in order to create a double of an ActiveRecord object. What's unique about it is that it already has stubbed most of the methods that are included in the ActiveRecord object, like save, create, and build, for you.
You can use ‘stub-model’ to stub certain behaviors. ActiveRecord test doubles become most useful when you are trying to create something that acts like an ActiveRecord object but doesn’t hit the database. You can check out more in the documentation.
Using these tips and techniques you should be able to write specs for all of your Rails app models.
Working With Rails Helper Specs
Working with Rails helper specs is almost as easy as working with models. We can work with them in isolation, and there is no request/response cycle for us to worry about.
However, there is one important feature to note, and an object called helper that can be used in our examples.
Let's start by creating a spec helper file:
We will define a simple method inside our helpers/application_helper.rb file for demonstration.
In the above example, you’ll notice how we called the method using the helper. Remember helpers are ruby modules, not ruby classes. We could have simply included the module, then had access to all the methods in our spec files.
However, using the helper has two advantages;
- The helper method also includes all of the rails built-in helpers, which automatically gives us access to any of those.
- Secondly, and more importantly, we can assign an instance variable that will normally be present whenever any of our helper methods are used inside the view. The example below will give you more insight into what I mean here.
If #next_page method doesn't recognize it, it will initialize 0 and add 1 to it. Accessing the method via the helper object is like using the technique in its proper context, instead of trying to use it abstractly out of context.
For more examples of this, see the helper spec docs.
By now you should feel more comfortable running tests on your model and helper specs. Model specs are like the sine qua non of unit testings, which is an important part of Test Driven Development. Unit testing ensures the smallest testable parts of your application work properly.
In the next article, we’ll dive into understanding controller specs and feature testing using Capybara.
To learn more about Microverse, and joining our supportive community of remote software developers, get started below!