Setting up BDD RSpec Test Suite for Rails API
Tags: rspec, rails, testing, tdd
Published: 2020-02-10 16:45:49

# Setting up BDD RSpec Test Suite for Rails API
RSpec although it does not come with built-in Rails Gem but is globally used to test Rails. MiniTest comes packaged with Ruby on Rails project creation.
In this tutorial, I will be setting up a new Rails API with RSpec testing suite enabled and disabling the MiniTest suite.

## Create Rails API
With Rails 5, there comes an option to create API only Rails project. To do this open terminal and navigate to the working directory and write:
```bash
rails new rspec-test-api --api -T
```
This command will create a new Ruby on Rails API with the SQLite database and skipping the MiniTest testing suite. `--api` says that don’t include HTML, styling and JS files. `-T` says skip the test suite.

## Adding RSpec To Gemfile
Now open `Gemfile` in your favorite editor and add following lines to block of development and test:
```ruby
group :development, :test do
  ...
  # For rspec testing
  gem 'rspec-rails', '~> 3.9'
  gem 'factory_bot_rails', '~> 5.1', '>= 5.1.1'
end
```
Here `rspec-rails` is the rails gem for RSpec. `factory_bot_rails` is Gem used to mock the DB data for testing purposes.
- [RSpec Rails Gem](https://github.com/rspec/rspec-rails "rspec rails gem link")
- [FactoryBotRails Gem](https://github.com/thoughtbot/factory_bot_rails "factory bot rails gem link")

Run `bundle install` in terminal to install gems.

Now in terminal write following line to initial RSpec:
```bash
rails generate rspec:install
```
This will add three files to the project.
Open `.rspec` in an editor and add the following line:
```bash
--require spec_helper
--format documentation
```
Now open `spec/spec_helper.rb` and replace the contents of the file with the following code:
```
RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

  config.shared_context_metadata_behavior = :apply_to_host_groups

  config.before(:suite) do
    # reindex models
    # and disable callbacks
    # Searchkick.disable_callbacks
  end
end
```
Now open `spec/rails_helper.rb` and replace the contents of the file with the following code:
```ruby
require File.expand_path('../config/environment', __dir__)
ENV['RAILS_ENV'] ||= 'test'
require 'rspec/rails'
require 'spec_helper'
include ActiveJob::TestHelper

FactoryBot::SyntaxRunner.class_eval do
  include ActionDispatch::TestProcess
end

abort('The Rails environment is running in production mode!') if Rails.env.production?

ActiveRecord::Migration.maintain_test_schema!
ActiveJob::Base.queue_adapter = :test
FactoryBot.rewind_sequences

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!

  config.filter_rails_from_backtrace!
end
```
Other helpers like JWT user token generation are written in rails helper file.
To remove extra files creation of RSpec while scaffolding add following lines to `config/application.rb`:
```ruby
module RSpecTestApi
  class Application < Rails::Application
    ...
    config.api_only = true
    config.generators do |g|
      g.test_framework :rspec,
                       fixtures: false,
                       view_specs: false,
                       helper_specs: false,
                       routing_specs: false,
                       controller_specs: false
    end
  end
end
```

## Spring Commands RSpec
`spring` gem comes builtin with Rails installations and helps to run the task fast in the terminal.
So now we want spring to run RSpec suite.
So, add a new Gem in `Gemfile` in development only block:
```ruby
group :development do
  ...
  gem 'spring-commands-rspec', '~> 1.0', '>= 1.0.4'
end
```
[Spring Commands RSpec Gem](https://github.com/jonleighton/spring-commands-rspec "spring commands rspec gem link")
Now in terminal write the following command:
```bash
bundle exec spring binstub rspec
```
Now run **`bin/rspec`** in the terminal and you will see that your RSpec is working like shown below:
```bash
Running via Spring preloader in process 3062
No examples found.

Finished in 0.00058 seconds (files took 0.09554 seconds to load)
0 examples, 0 failures
```
Now enter the tests and you are good to go.

> For testing API only, it is better to test models and then requests. There is no need to test the Controllers as they are not handling much of the frontend logic.

## Foot Note
Big Thanks to [Everyday Rails](https://everydayrails.com/ "everdayrails link") which helped me to understand and implement RSpec. Their book named [Testing with RSpec](https://leanpub.com/everydayrailsrspec "testing with rspec book link") is great to understand various scenarios to implement RSpec and testing rails comfortably. The Author’s Twitter handle is [@ruralocity](https://twitter.com/ruralocity "Aaron Sumner Twitter").